I have an http server with an endpoint that returns lots of data streamed from a db. The response is chunked (< Transfer-Encoding: chunked
). And if I run into an error, like the DB crashing, I can use a panic & curl will warn me of an issue:
curl: (18) transfer closed with outstanding read data remaining
I don't want a panic though - I just want a simple log message. And if I recover()
I don't get the error in curl so there's no indication of something breaking.
Is there a way to break an chunked http response without a panic?
That error you see from curl is because the connection was immediately closed by the http server when it saw the panic. In order to force the connection closed without a panic
, you will have to hijack it:
// inside the http handler
// func(w http.ResponseWriter, r *http.Request) {
// to abort an HTTP/1.1 response
if w, ok := w.(http.Hijacker); ok {
c, _, err := w.Hijack()
if err != nil {
log.Println("cannot close connection:", err)
return
}
c.Close()
return
}
In Go 1.7, hijacking (as proposed in JimB's answer) is probably the best solution. Unfortunately, it only works in HTTP/1.1 — it will not do anything useful in HTTP/2.
Go 1.8 introduces a new value ErrAbortHandler
, and the official way of interrupting an HTTP reply mid-stream is panic(http.ErrAbortHandler)
, which works for both HTTP/1.1 and HTTP.2. This is described in issue 17790.