How can I customize HTTP 400 responses for parsing errors?
I wrote a REST API service that requires all responses to be in JSON format. However, when the Go HTTP request parser encounters an error, it returns 400 as a plain text response, never calling my handlers. Example:
> curl -i -H 'Authorization: Basic hi
there' 'http://localhost:8080/test' -v
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Authorization: Basic hi
> there
>
< HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
< Content-Type: text/plain; charset=utf-8
Content-Type: text/plain; charset=utf-8
< Connection: close
Connection: close
<
* Closing connection 0
Note the incorrect authorization header. Of course 400 is the correct answer, but it's text / simple, of course. Is there any way to configure the Go http parser to use custom media types and media bodies with an error response?
source to share
You can not. You can find this in the net / http source, this will only happen if the request was malformed:
https://github.com/golang/go/blob/master/src/net/http/server.go#L1744
I think your problem might be a newline in the header you are adding to curl?
401, 403, 404, 500 errors you will be able to respond with json, but bad requests or bad headers (too long, incorrect) are handled in server.go.
It is currently not possible to catch errors like this, although it is under considerations , so your only solution in go is to fix the source stdlib (I do not recommend this). However, since this error only occurs if the client made a mistake and the request is malformed, this is probably not a big problem. The reason for the text response is that the browser or similar client (like curl without -v) doesn't just see an empty response. You can put a proxy like nginx in front of your application, but then you never see the request, since it is a bad request, your proxy will handle it.
You might be able to do this with a proxy like nginx, but what if you set a specific static error page to serve 400 errors and serve the 400.json file you specified? This is the only solution I can think of. For nginx, the following directive can work:
error_page 400 /400.json;
If you would like to customize these errors, perhaps add a comment on the issue related to let them know that you have this specific issue.
source to share
If you are using net / http standard library you can use the following code. Take a look at this answer Showing custom 404 error page with default http @Mostafa package which I got this example from
func homeHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
errorHandler(w, r, http.StatusNotFound)
return
}
fmt.Fprint(w, "welcome home")
}
func errorHandler(w http.ResponseWriter, r *http.Request, status int) {
w.WriteHeader(status)
if status == http.StatusNotFound {
// JSON Out here
}
}
source to share