« Back to Index

Go: HTTP handler Write error after WriteHeader

View original Gist on GitHub

Tags: #go #http #middleware

example.go

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