frontend: add footer (session id + request id)
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
parent
6a5ba2a51d
commit
2f5cbd5eee
2 changed files with 47 additions and 25 deletions
|
@ -27,17 +27,17 @@ func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
log.WithField("currency", currentCurrency(r)).Info("home")
|
log.WithField("currency", currentCurrency(r)).Info("home")
|
||||||
currencies, err := fe.getCurrencies(r.Context())
|
currencies, err := fe.getCurrencies(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
products, err := fe.getProducts(r.Context())
|
products, err := fe.getProducts(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve products"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve products"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cart, err := fe.getCart(r.Context(), sessionID(r))
|
cart, err := fe.getCart(r.Context(), sessionID(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,17 +49,18 @@ func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
for i, p := range products {
|
for i, p := range products {
|
||||||
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
|
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrapf(err, "failed to do currency conversion for product %s", p.GetId()), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrapf(err, "failed to do currency conversion for product %s", p.GetId()), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ps[i] = productView{p, price}
|
ps[i] = productView{p, price}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := templates.ExecuteTemplate(w, "home", map[string]interface{}{
|
if err := templates.ExecuteTemplate(w, "home", map[string]interface{}{
|
||||||
|
"session_id": sessionID(r),
|
||||||
|
"request_id": r.Context().Value(ctxKeyRequestID{}),
|
||||||
"user_currency": currentCurrency(r),
|
"user_currency": currentCurrency(r),
|
||||||
"currencies": currencies,
|
"currencies": currencies,
|
||||||
"products": ps,
|
"products": ps,
|
||||||
"session_id": sessionID(r),
|
|
||||||
"cart_size": len(cart),
|
"cart_size": len(cart),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
@ -70,7 +71,7 @@ func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request)
|
||||||
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
|
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
|
||||||
id := mux.Vars(r)["id"]
|
id := mux.Vars(r)["id"]
|
||||||
if id == "" {
|
if id == "" {
|
||||||
renderHTTPError(log, w, errors.New("product id not specified"), http.StatusBadRequest)
|
renderHTTPError(log, r, w, errors.New("product id not specified"), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.WithField("id", id).WithField("currency", currentCurrency(r)).
|
log.WithField("id", id).WithField("currency", currentCurrency(r)).
|
||||||
|
@ -78,30 +79,30 @@ func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request)
|
||||||
|
|
||||||
p, err := fe.getProduct(r.Context(), id)
|
p, err := fe.getProduct(r.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve product"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve product"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currencies, err := fe.getCurrencies(r.Context())
|
currencies, err := fe.getCurrencies(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cart, err := fe.getCart(r.Context(), sessionID(r))
|
cart, err := fe.getCart(r.Context(), sessionID(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
|
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "failed to convert currency"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "failed to convert currency"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
recommendations, err := fe.getRecommendations(r.Context(), sessionID(r), []string{id})
|
recommendations, err := fe.getRecommendations(r.Context(), sessionID(r), []string{id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "failed to get product recommendations"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "failed to get product recommendations"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,10 +112,11 @@ func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request)
|
||||||
}{p, price}
|
}{p, price}
|
||||||
|
|
||||||
if err := templates.ExecuteTemplate(w, "product", map[string]interface{}{
|
if err := templates.ExecuteTemplate(w, "product", map[string]interface{}{
|
||||||
|
"session_id": sessionID(r),
|
||||||
|
"request_id": r.Context().Value(ctxKeyRequestID{}),
|
||||||
"user_currency": currentCurrency(r),
|
"user_currency": currentCurrency(r),
|
||||||
"currencies": currencies,
|
"currencies": currencies,
|
||||||
"product": product,
|
"product": product,
|
||||||
"session_id": sessionID(r),
|
|
||||||
"recommendations": recommendations,
|
"recommendations": recommendations,
|
||||||
"cart_size": len(cart),
|
"cart_size": len(cart),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
@ -127,19 +129,19 @@ func (fe *frontendServer) addToCartHandler(w http.ResponseWriter, r *http.Reques
|
||||||
quantity, _ := strconv.ParseUint(r.FormValue("quantity"), 10, 32)
|
quantity, _ := strconv.ParseUint(r.FormValue("quantity"), 10, 32)
|
||||||
productID := r.FormValue("product_id")
|
productID := r.FormValue("product_id")
|
||||||
if productID == "" || quantity == 0 {
|
if productID == "" || quantity == 0 {
|
||||||
renderHTTPError(log, w, errors.New("invalid form input"), http.StatusBadRequest)
|
renderHTTPError(log, r, w, errors.New("invalid form input"), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.WithField("product", productID).WithField("quantity", quantity).Debug("adding to cart")
|
log.WithField("product", productID).WithField("quantity", quantity).Debug("adding to cart")
|
||||||
|
|
||||||
p, err := fe.getProduct(r.Context(), productID)
|
p, err := fe.getProduct(r.Context(), productID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve product"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve product"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := fe.insertCart(r.Context(), sessionID(r), p.GetId(), int32(quantity)); err != nil {
|
if err := fe.insertCart(r.Context(), sessionID(r), p.GetId(), int32(quantity)); err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "failed to add to cart"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "failed to add to cart"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("location", "/cart")
|
w.Header().Set("location", "/cart")
|
||||||
|
@ -151,7 +153,7 @@ func (fe *frontendServer) emptyCartHandler(w http.ResponseWriter, r *http.Reques
|
||||||
log.Debug("emptying cart")
|
log.Debug("emptying cart")
|
||||||
|
|
||||||
if err := fe.emptyCart(r.Context(), sessionID(r)); err != nil {
|
if err := fe.emptyCart(r.Context(), sessionID(r)); err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "failed to empty cart"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "failed to empty cart"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("location", "/")
|
w.Header().Set("location", "/")
|
||||||
|
@ -163,24 +165,24 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request
|
||||||
log.Debug("view user cart")
|
log.Debug("view user cart")
|
||||||
currencies, err := fe.getCurrencies(r.Context())
|
currencies, err := fe.getCurrencies(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cart, err := fe.getCart(r.Context(), sessionID(r))
|
cart, err := fe.getCart(r.Context(), sessionID(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
recommendations, err := fe.getRecommendations(r.Context(), sessionID(r), cartIDs(cart))
|
recommendations, err := fe.getRecommendations(r.Context(), sessionID(r), cartIDs(cart))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "failed to get product recommendations"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "failed to get product recommendations"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
shippingCost, err := fe.getShippingQuote(r.Context(), cart, currentCurrency(r))
|
shippingCost, err := fe.getShippingQuote(r.Context(), cart, currentCurrency(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "failed to get shipping quote"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "failed to get shipping quote"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,12 +196,12 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request
|
||||||
for i, item := range cart {
|
for i, item := range cart {
|
||||||
p, err := fe.getProduct(r.Context(), item.GetProductId())
|
p, err := fe.getProduct(r.Context(), item.GetProductId())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrapf(err, "could not retrieve product #%s", item.GetProductId()), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrapf(err, "could not retrieve product #%s", item.GetProductId()), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
|
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrapf(err, "could not convert currency for product #%s", item.GetProductId()), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrapf(err, "could not convert currency for product #%s", item.GetProductId()), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,9 +216,10 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request
|
||||||
|
|
||||||
year := time.Now().Year()
|
year := time.Now().Year()
|
||||||
if err := templates.ExecuteTemplate(w, "cart", map[string]interface{}{
|
if err := templates.ExecuteTemplate(w, "cart", map[string]interface{}{
|
||||||
|
"session_id": sessionID(r),
|
||||||
|
"request_id": r.Context().Value(ctxKeyRequestID{}),
|
||||||
"user_currency": currentCurrency(r),
|
"user_currency": currentCurrency(r),
|
||||||
"currencies": currencies,
|
"currencies": currencies,
|
||||||
"session_id": sessionID(r),
|
|
||||||
"recommendations": recommendations,
|
"recommendations": recommendations,
|
||||||
"cart_size": len(cart),
|
"cart_size": len(cart),
|
||||||
"shipping_cost": shippingCost,
|
"shipping_cost": shippingCost,
|
||||||
|
@ -263,7 +266,7 @@ func (fe *frontendServer) placeOrderHandler(w http.ResponseWriter, r *http.Reque
|
||||||
Country: country},
|
Country: country},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
renderHTTPError(log, w, errors.Wrap(err, "failed to complete the order"), http.StatusInternalServerError)
|
renderHTTPError(log, r, w, errors.Wrap(err, "failed to complete the order"), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.WithField("order", order.GetOrder().GetOrderId()).Info("order placed")
|
log.WithField("order", order.GetOrder().GetOrderId()).Info("order placed")
|
||||||
|
@ -278,6 +281,7 @@ func (fe *frontendServer) placeOrderHandler(w http.ResponseWriter, r *http.Reque
|
||||||
|
|
||||||
if err := templates.ExecuteTemplate(w, "order", map[string]interface{}{
|
if err := templates.ExecuteTemplate(w, "order", map[string]interface{}{
|
||||||
"session_id": sessionID(r),
|
"session_id": sessionID(r),
|
||||||
|
"request_id": r.Context().Value(ctxKeyRequestID{}),
|
||||||
"user_currency": currentCurrency(r),
|
"user_currency": currentCurrency(r),
|
||||||
"order": order.GetOrder(),
|
"order": order.GetOrder(),
|
||||||
"total_paid": &totalPaid,
|
"total_paid": &totalPaid,
|
||||||
|
@ -320,12 +324,14 @@ func (fe *frontendServer) setCurrencyHandler(w http.ResponseWriter, r *http.Requ
|
||||||
w.WriteHeader(http.StatusFound)
|
w.WriteHeader(http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderHTTPError(log logrus.FieldLogger, w http.ResponseWriter, err error, code int) {
|
func renderHTTPError(log logrus.FieldLogger, r *http.Request, w http.ResponseWriter, err error, code int) {
|
||||||
log.WithField("error", err).Error("request error")
|
log.WithField("error", err).Error("request error")
|
||||||
errMsg := fmt.Sprintf("%+v", err)
|
errMsg := fmt.Sprintf("%+v", err)
|
||||||
|
|
||||||
w.WriteHeader(code)
|
w.WriteHeader(code)
|
||||||
templates.ExecuteTemplate(w, "error", map[string]interface{}{
|
templates.ExecuteTemplate(w, "error", map[string]interface{}{
|
||||||
|
"session_id": sessionID(r),
|
||||||
|
"request_id": r.Context().Value(ctxKeyRequestID{}),
|
||||||
"error": errMsg,
|
"error": errMsg,
|
||||||
"status_code": code,
|
"status_code": code,
|
||||||
"status": http.StatusText(code)})
|
"status": http.StatusText(code)})
|
||||||
|
|
|
@ -1,4 +1,20 @@
|
||||||
{{ define "footer" }}
|
{{ define "footer" }}
|
||||||
|
<footer class="py-5 px-5">
|
||||||
|
<div class="container">
|
||||||
|
<p>© 2018 Google Inc</p>
|
||||||
|
<p>
|
||||||
|
<small class="text-muted">
|
||||||
|
This website is hosted for demo purposes only. It is not an
|
||||||
|
actual shop. This is not an official Google project.
|
||||||
|
</small>
|
||||||
|
</p>
|
||||||
|
<small class="text-muted">
|
||||||
|
{{ if $.session_id }}session-id: {{ $.session_id }}</br>{{end}}
|
||||||
|
{{ if $.request_id }}request-id: {{ $.request_id }}</br>{{end}}
|
||||||
|
</small>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue