18/08/2024 - GO
Go's net/http router is updated but it doesn't provide a way to easily manage 404 Not Found
and 405 Method Not Allowed
for JSON APIs. For instance, JSON response header and body. Here is an example how you can accomplish it yourself. What it does is simple. Custom middleware intercepts the response, overrides it and writes it. You can extend it as you wish.
package main
import (
"net/http"
)
func main() {
rtr := http.NewServeMux()
rtr.HandleFunc("GET /v1", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`GET /v1`)) })
rtr.HandleFunc("POST /v1", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`POST /v1`)) })
rtr.HandleFunc("GET /v1/users", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`GET /v1/users`)) })
rtr.HandleFunc("POST /v1/users", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`POST /v1/users`)) })
rtr.HandleFunc("POST /v1/{channel}/users", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`POST /v1/{channel}/users`)) })
http.ListenAndServe(":8888", InterceptResponse(rtr))
}
func InterceptResponse(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(&OverrideResponse{ResponseWriter: w}, r)
})
}
type OverrideResponse struct {
http.ResponseWriter
status int
override bool
}
func (o *OverrideResponse) WriteHeader(status int) {
if o.Header().Get("Content-Type") == "text/plain; charset=utf-8" {
o.Header().Set("Content-Type", "application/json; charset=utf-8")
o.override = true
}
o.status = status
o.ResponseWriter.WriteHeader(status)
}
func (o *OverrideResponse) Write(body []byte) (int, error) {
if o.override {
switch o.status {
case http.StatusNotFound:
body = []byte(`{"code": "route_not_found"}`)
case http.StatusMethodNotAllowed:
body = []byte(`{"code": "method_not_allowed"}`)
}
}
return o.ResponseWriter.Write(body)
}
PUT http://localhost:8888/v1/users
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json; charset=utf-8
{"code": "method_not_allowed"}
PUT http://localhost:8888/v1/posts
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{"code": "route_not_found"}