Skip to content

Commit 50f1bfe

Browse files
committed
working apiservice
1 parent 7ac94a9 commit 50f1bfe

File tree

4 files changed

+94
-33
lines changed

4 files changed

+94
-33
lines changed

src/apiservice/README.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
# frontend
1+
# apiservice
22

3-
Run the following command to restore dependencies to `vendor/` directory:
3+
This is a stripped down version of the `frontend` application that just return json.
4+
ex:
45

5-
dep ensure --vendor-only
6+
```
7+
curl -s "http://apiservice:8080/api/v1/"|jq '.'
8+
curl -s "http://apiservice:8080/api/v1/product/OLJCESPC7Z"|jq '.'
9+
```

src/apiservice/handlers.go

+82-28
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import (
1818
"context"
1919
"encoding/json"
2020
"fmt"
21-
"html/template"
2221
"math/rand"
2322
"net/http"
23+
"os"
2424
"strconv"
2525
"time"
2626

@@ -32,12 +32,56 @@ import (
3232
"github.com/GoogleCloudPlatform/microservices-demo/src/frontend/money"
3333
)
3434

35-
var (
36-
templates = template.Must(template.New("").
37-
Funcs(template.FuncMap{
38-
"renderMoney": renderMoney,
39-
}).ParseGlob("templates/*.html"))
40-
)
35+
func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
36+
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
37+
log.WithField("currency", currentCurrency(r)).Info("home")
38+
currencies, err := fe.getCurrencies(r.Context())
39+
if err != nil {
40+
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
41+
return
42+
}
43+
products, err := fe.getProducts(r.Context())
44+
if err != nil {
45+
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve products"), http.StatusInternalServerError)
46+
return
47+
}
48+
cart, err := fe.getCart(r.Context(), sessionID(r))
49+
if err != nil {
50+
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
51+
return
52+
}
53+
54+
type productView struct {
55+
Item *pb.Product
56+
Price *pb.Money
57+
}
58+
ps := make([]productView, len(products))
59+
for i, p := range products {
60+
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
61+
if err != nil {
62+
renderHTTPError(log, r, w, errors.Wrapf(err, "failed to do currency conversion for product %s", p.GetId()), http.StatusInternalServerError)
63+
return
64+
}
65+
ps[i] = productView{p, price}
66+
}
67+
68+
finalData := map[string]interface{}{
69+
"session_id": sessionID(r),
70+
"request_id": r.Context().Value(ctxKeyRequestID{}),
71+
"user_currency": currentCurrency(r),
72+
"currencies": currencies,
73+
"products": ps,
74+
"cart_size": len(cart),
75+
"banner_color": os.Getenv("BANNER_COLOR"), // illustrates canary deployments
76+
"ad": fe.chooseAd(r.Context(), []string{}, log),
77+
}
78+
79+
b, err := json.Marshal(finalData)
80+
if err != nil {
81+
log.Println(err)
82+
}
83+
w.Write(b)
84+
}
4185

4286
func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request) {
4387
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
@@ -68,9 +112,9 @@ func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request)
68112

69113
b, err := json.Marshal(product)
70114
if err != nil {
71-
log.Println(b)
115+
log.Println(err)
72116
}
73-
117+
w.Write(b)
74118
}
75119

76120
func (fe *frontendServer) addToCartHandler(w http.ResponseWriter, r *http.Request) {
@@ -165,18 +209,18 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request
165209

166210
year := time.Now().Year()
167211

168-
var finalCart = map[string]interface{}{
169-
"session_id": sessionID(r),
170-
"request_id": r.Context().Value(ctxKeyRequestID{}),
171-
"user_currency": currentCurrency(r),
172-
"currencies": currencies,
173-
"recommendations": recommendations,
174-
"cart_size": len(cart),
175-
"shipping_cost": shippingCost,
176-
"total_cost": totalPrice,
177-
"items": items,
178-
"expiration_years": []int{year, year + 1, year + 2, year + 3, year + 4},
179-
}
212+
var finalCart = map[string]interface{}{
213+
"session_id": sessionID(r),
214+
"request_id": r.Context().Value(ctxKeyRequestID{}),
215+
"user_currency": currentCurrency(r),
216+
"currencies": currencies,
217+
"recommendations": recommendations,
218+
"cart_size": len(cart),
219+
"shipping_cost": shippingCost,
220+
"total_cost": totalPrice,
221+
"items": items,
222+
"expiration_years": []int{year, year + 1, year + 2, year + 3, year + 4},
223+
}
180224

181225
b, err := json.Marshal(finalCart)
182226
if err != nil {
@@ -232,15 +276,18 @@ func (fe *frontendServer) placeOrderHandler(w http.ResponseWriter, r *http.Reque
232276
totalPaid = money.Must(money.Sum(totalPaid, *v.GetCost()))
233277
}
234278

235-
if err := templates.ExecuteTemplate(w, "order", map[string]interface{}{
279+
var finalData = map[string]interface{}{
236280
"session_id": sessionID(r),
237281
"request_id": r.Context().Value(ctxKeyRequestID{}),
238282
"user_currency": currentCurrency(r),
239283
"order": order.GetOrder(),
240284
"total_paid": &totalPaid,
241285
"recommendations": recommendations,
242-
}); err != nil {
243-
log.Println(err)
286+
}
287+
288+
b, err := json.Marshal(finalData)
289+
if err != nil {
290+
log.Println(b)
244291
}
245292
}
246293

@@ -252,7 +299,7 @@ func (fe *frontendServer) logoutHandler(w http.ResponseWriter, r *http.Request)
252299
c.MaxAge = -1
253300
http.SetCookie(w, c)
254301
}
255-
w.Header().Set("Location", "/")
302+
w.Header().Set("Location", "/api/v1")
256303
w.WriteHeader(http.StatusFound)
257304
}
258305

@@ -271,7 +318,7 @@ func (fe *frontendServer) setCurrencyHandler(w http.ResponseWriter, r *http.Requ
271318
}
272319
referer := r.Header.Get("referer")
273320
if referer == "" {
274-
referer = "/"
321+
referer = "/api/v1"
275322
}
276323
w.Header().Set("Location", referer)
277324
w.WriteHeader(http.StatusFound)
@@ -293,12 +340,19 @@ func renderHTTPError(log logrus.FieldLogger, r *http.Request, w http.ResponseWri
293340
errMsg := fmt.Sprintf("%+v", err)
294341

295342
w.WriteHeader(code)
296-
templates.ExecuteTemplate(w, "error", map[string]interface{}{
343+
var finalData = map[string]interface{}{
297344
"session_id": sessionID(r),
298345
"request_id": r.Context().Value(ctxKeyRequestID{}),
299346
"error": errMsg,
300347
"status_code": code,
301-
"status": http.StatusText(code)})
348+
"status": http.StatusText(code),
349+
}
350+
351+
b, err := json.Marshal(finalData)
352+
if err != nil {
353+
w.Write(b)
354+
}
355+
302356
}
303357

304358
func currentCurrency(r *http.Request) string {

src/apiservice/main.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,17 @@ func main() {
122122
mustConnGRPC(ctx, &svc.adSvcConn, svc.adSvcAddr)
123123

124124
r := mux.NewRouter()
125+
r.HandleFunc("/", svc.homeHandler).Methods(http.MethodGet, http.MethodHead)
126+
r.HandleFunc("/api/v1", svc.homeHandler).Methods(http.MethodGet, http.MethodHead)
125127
r.HandleFunc("/api/v1/product/{id}", svc.productHandler).Methods(http.MethodGet, http.MethodHead)
126128
r.HandleFunc("/api/v1/cart", svc.viewCartHandler).Methods(http.MethodGet, http.MethodHead)
127129
r.HandleFunc("/api/v1/cart", svc.addToCartHandler).Methods(http.MethodPost)
128130
r.HandleFunc("/api/v1/cart/empty", svc.emptyCartHandler).Methods(http.MethodPost)
129131
r.HandleFunc("/api/v1/setCurrency", svc.setCurrencyHandler).Methods(http.MethodPost)
130132
r.HandleFunc("/api/v1/logout", svc.logoutHandler).Methods(http.MethodGet)
131133
r.HandleFunc("/api/v1/cart/checkout", svc.placeOrderHandler).Methods(http.MethodPost)
132-
r.HandleFunc("/api/v1/robots.txt", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "User-agent: *\nDisallow: /") })
133-
r.HandleFunc("/api/v1/_healthz", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "ok") })
134+
r.HandleFunc("/robots.txt", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "User-agent: *\nDisallow: /") })
135+
r.HandleFunc("/_healthz", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "ok") })
134136

135137
// also init the prometheus handler
136138
initPrometheusStats(log, r)

tanka/lib/hipstershop/frontend.libsonnet

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
SHIPPING_SERVICE_ADDR: $._config.shippingservice.URL,
3939
CHECKOUT_SERVICE_ADDR: $._config.checkoutservice.URL,
4040
AD_SERVICE_ADDR: $._config.adservice.URL,
41+
// BANNER_COLOR: "red",
4142
// JAEGER_SERVICE_ADDR: "jaeger-collector:14268",
4243
},
4344
readinessProbe: container.mixin.readinessProbe.httpGet.withPath("/_healthz")

0 commit comments

Comments
 (0)