A client can send anything: no name, a price written as text, a negative number. Never trust input. Before you store something, check it, and if it's wrong, answer 400 Bad Request with an error that tells the client what to fix. A 400 says the client made a mistake; a 500 says your server broke.
Two things about Decode help. A field the JSON doesn't have keeps the value it had before, so a missing string stays "" and a missing int stays whatever you started it with. And Decode returns an error when a value doesn't fit its field, like the text "5" for an int. Here is the idea on another route:
type Rating struct {
Stars int `json:"stars"`
}
app.HandleFunc("POST /ratings", func(w http.ResponseWriter, r *http.Request) {
var data Rating
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil || data.Stars < 1 || data.Stars > 5 {
writeJSON(w, 400, map[string]string{"error": "Stars must be a whole number from 1 to 5"})
return
}
writeJSON(w, 201, data)
})
writeJSON sends the answer, but only return stops the handler, so a refused product is never stored. Your code must give, in this order:
POST /products {"price": 5, "category": "home"} → 400 {"error": "Name is required"}
POST /products {"name": "", "price": 5, "category": "home"} → 400 {"error": "Name is required"}
POST /products {"name": "Cup", "category": "kitchen"} → 400 {"error": "Price must be a whole number of 0 or more"}
POST /products {"name": "Cup", "price": "5", "category": "kitchen"} → 400 the same price error
POST /products {"name": "Cup", "price": -1, "category": "kitchen"} → 400 the same price error
POST /products {"name": "Cup", "price": 4.5, "category": "kitchen"} → 400 the same price error
POST /products {"name": "Sticker", "price": 0, "category": "office"} → 201 {"id": 5, "name": "Sticker", "price": 0, "category": "office"}
GET /products/count → 200 {"count": 5}
Your task: in the POST handler, start data with a price of -1, keep the error Decode returns, and answer 400 with the right error when the name is missing or empty or the price isn't a whole number of 0 or more.
Assignment
Follow the Coding Tutorial to add the name check and the price check to the POST handler.
Hint
Each check is an if with a return inside it, right after the 400 answer. A missing price keeps the -1 data started with, and a price that isn't a whole number makes err not nil.
Free plan: 30 tutor messages. PRO is unlimited.
