Tags: #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.")
}