frontend: error page
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
parent
7f4319ae54
commit
b2ca0868a5
2 changed files with 35 additions and 24 deletions
|
@ -36,7 +36,7 @@ func ensureSessionID(next http.HandlerFunc) http.HandlerFunc {
|
||||||
MaxAge: cookieMaxAge,
|
MaxAge: cookieMaxAge,
|
||||||
})
|
})
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("unrecognized cookie error: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("unrecognized cookie error: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
sessionID = c.Value
|
sessionID = c.Value
|
||||||
|
@ -51,17 +51,17 @@ func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("[home] session_id=%s currency=%s", sessionID(r), currentCurrency(r))
|
log.Printf("[home] session_id=%s currency=%s", sessionID(r), currentCurrency(r))
|
||||||
currencies, err := fe.getCurrencies(r.Context())
|
currencies, err := fe.getCurrencies(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve currencies: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve currencies: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
products, err := fe.getProducts(r.Context())
|
products, err := fe.getProducts(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve products: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve products: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve cart: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve cart: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ 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 {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
renderHTTPError(w, err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ps[i] = productView{p, price}
|
ps[i] = productView{p, price}
|
||||||
|
@ -93,36 +93,36 @@ func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request) {
|
func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
id := mux.Vars(r)["id"]
|
id := mux.Vars(r)["id"]
|
||||||
if id == "" {
|
if id == "" {
|
||||||
http.Error(w, "product id not specified", http.StatusBadRequest)
|
renderHTTPError(w, fmt.Errorf("product id not specified"), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Printf("[productHandler] id=%s currency=%s session=%s", id, currentCurrency(r), sessionID(r))
|
log.Printf("[productHandler] id=%s currency=%s session=%s", id, currentCurrency(r), sessionID(r))
|
||||||
p, err := fe.getProduct(r.Context(), id)
|
p, err := fe.getProduct(r.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve product: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve product: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currencies, err := fe.getCurrencies(r.Context())
|
currencies, err := fe.getCurrencies(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve currencies: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve currencies: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve cart: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve cart: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("failed to convert currency: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("failed to convert currency: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("failed to get product recommendations: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("failed to get product recommendations: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,19 +147,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 {
|
||||||
http.Error(w, "invalid form input", http.StatusBadRequest)
|
renderHTTPError(w, fmt.Errorf("invalid form input"), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Printf("[addToCart] product_id=%s qty=%d session_id=%s", productID, quantity, sessionID(r))
|
log.Printf("[addToCart] product_id=%s qty=%d session_id=%s", productID, quantity, sessionID(r))
|
||||||
|
|
||||||
p, err := fe.getProduct(r.Context(), productID)
|
p, err := fe.getProduct(r.Context(), productID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve product: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve product: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("failed to add to cart: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("failed to add to cart: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("location", "/cart")
|
w.Header().Set("location", "/cart")
|
||||||
|
@ -170,7 +170,7 @@ func (fe *frontendServer) emptyCartHandler(w http.ResponseWriter, r *http.Reques
|
||||||
log.Printf("[emptyCart] session_id=%s", sessionID(r))
|
log.Printf("[emptyCart] session_id=%s", sessionID(r))
|
||||||
|
|
||||||
if err := fe.emptyCart(r.Context(), sessionID(r)); err != nil {
|
if err := fe.emptyCart(r.Context(), sessionID(r)); err != nil {
|
||||||
http.Error(w, fmt.Sprintf("failed to empty cart: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("failed to empty cart: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("location", "/")
|
w.Header().Set("location", "/")
|
||||||
|
@ -181,24 +181,24 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request
|
||||||
log.Printf("[viewCart] session_id=%s", sessionID(r))
|
log.Printf("[viewCart] session_id=%s", sessionID(r))
|
||||||
currencies, err := fe.getCurrencies(r.Context())
|
currencies, err := fe.getCurrencies(r.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve currencies: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve currencies: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve cart: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve cart: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("failed to get product recommendations: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("failed to get product recommendations: %+v", err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("failed to get shipping quote: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("failed to get shipping quote: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,12 +212,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 {
|
||||||
http.Error(w, fmt.Sprintf("could not retrieve product #%s: %+v", item.GetProductId(), err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not retrieve product #%s: %+v", item.GetProductId(), err), 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 {
|
||||||
http.Error(w, fmt.Sprintf("could not convert currency for product #%s: %+v", item.GetProductId(), err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("could not convert currency for product #%s: %+v", item.GetProductId(), err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ func (fe *frontendServer) placeOrderHandler(w http.ResponseWriter, r *http.Reque
|
||||||
Country: country},
|
Country: country},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, fmt.Sprintf("failed to complete the order: %+v", err), http.StatusInternalServerError)
|
renderHTTPError(w, fmt.Errorf("failed to complete the order: %+v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Printf("order #%s completed", order.GetOrder().GetOrderId())
|
log.Printf("order #%s completed", order.GetOrder().GetOrderId())
|
||||||
|
@ -359,6 +359,14 @@ func (fe *frontendServer) setCurrencyHandler(w http.ResponseWriter, r *http.Requ
|
||||||
w.WriteHeader(http.StatusFound)
|
w.WriteHeader(http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderHTTPError(w http.ResponseWriter, err error, code int) {
|
||||||
|
w.WriteHeader(code)
|
||||||
|
templates.ExecuteTemplate(w, "error", map[string]interface{}{
|
||||||
|
"error": err.Error(),
|
||||||
|
"status_code": code,
|
||||||
|
"status": http.StatusText(code)})
|
||||||
|
}
|
||||||
|
|
||||||
func currentCurrency(r *http.Request) string {
|
func currentCurrency(r *http.Request) string {
|
||||||
c, _ := r.Cookie(cookieCurrency)
|
c, _ := r.Cookie(cookieCurrency)
|
||||||
if c != nil {
|
if c != nil {
|
||||||
|
|
|
@ -6,8 +6,11 @@
|
||||||
<div class="container bg-light py-3 px-lg-5 py-lg-5">
|
<div class="container bg-light py-3 px-lg-5 py-lg-5">
|
||||||
<h1>Uh, oh!</h1>
|
<h1>Uh, oh!</h1>
|
||||||
<p>Something has failed. Below are some details for debugging.</p>
|
<p>Something has failed. Below are some details for debugging.</p>
|
||||||
<pre>
|
|
||||||
{{.errorMsg}}
|
<p><strong>HTTP Status:</strong> {{.status_code}} {{.status}}</p>
|
||||||
|
<pre class="border border-danger"
|
||||||
|
style="white-space: pre-wrap; word-break: keep-all;">
|
||||||
|
{{- .error -}}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue