An HTTP handler uses `WriteHeader` on its `http.ResponseWriter` to send a status code and response headers. Call it before writing the body. If `Write` happens first, the response gets the default status, `http.StatusOK`, and a later `WriteHeader` call is superfluous. section 8.7 section 8.2.1
Reject the wrong method
For `POST /games`, check the method before creating a game. A request using another method can call `w.WriteHeader(http.StatusMethodNotAllowed)` and return immediately. `curl -v localhost:8080/games` shows the resulting `405 Method Not Allowed` response with an empty body; a plain `curl` request may show nothing. section 8.2.1
Listing 8.9 handler.go: Setting the response message
func Handle(w http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
w.WriteHeader(http.StatusCreated)
_, _ = w.Write([]byte("Creating a new game"))
}
The handler sends `405` for the wrong method and `201 Created` before writing the success message. section 8.2.1
For a JSON response, set `Content-Type` with `w.Header().Set` before calling `WriteHeader(http.StatusCreated)`, then encode the body. Once the header has been sent, an encoding failure cannot be reported by changing that response; log the failure instead. A handler test can check the status, content type, and body with `httptest.NewRecorder`. section 8.2.1
Listing 8.11 newgame/handler.go: Returning a Game response
func Handle(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json") #1
w.WriteHeader(http.StatusCreated)
apiGame := api.GameResponse{} #2
err := json.NewEncoder(w).Encode(apiGame) #3
if err != nil { #4
// The header has already been set. Nothing much we can do here.
log.Printf("failed to write response: %s", err)
}
}
Shows header setup, `201 Created`, JSON encoding, and logging if writing the response fails. section 8.2.1
