Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active May 30, 2025 08:42
Show Gist options
  • Save Integralist/fc7a7bb75e2951ffe4310a2620b73e8f to your computer and use it in GitHub Desktop.
Save Integralist/fc7a7bb75e2951ffe4310a2620b73e8f to your computer and use it in GitHub Desktop.
Go: HTTP handler Write error after WriteHeader #go #http #middleware
func exampleHandler(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
// The net/http server itself has a recovery mechanism that specifically looks for http.ErrAbortHandler.
// When it catches this particular panic, it knows to abort the current request handler and close the connection.
if rec == http.ErrAbortHandler {
log.Println("Handler aborted with http.ErrAbortHandler. Connection will be closed by server.")
} else {
log.Printf("Unhandled panic: %v.", rec)
}
// Now that we've implemented our own custom logging for this panic,
// we re-raise the panic so that the net/http server's default panic handler can take over.
panic(rec)
}
}()
w.WriteHeader(http.StatusOK)
_, err := w.Write([]byte("This is a successful response.\n"))
if err != nil {
// The client has already received the 200 OK header but will now get an incomplete response body.
log.Printf("Error writing successful response body: %v. Panicking with ErrAbortHandler.", err)
// ErrAbortHandler is a sentinel panic value to abort a handler.
// While any panic from ServeHTTP aborts the response to the client,
// panicking with ErrAbortHandler also suppresses logging of a stack trace to the server's error log.
panic(http.ErrAbortHandler)
}
log.Println("Successfully wrote response body.")
}
@cee-dub
Copy link

cee-dub commented May 27, 2025

Does this work without re-panicking the sentinel value in the “if” block?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment