Consider a test HTTP server in Go:
package main
import "net/http"
func myHandler1(w http.ResponseWriter, r *http.Request) {
panic("I panicked")
}
func myHandler2(w http.ResponseWriter, r *http.Request) {
panic(http.ErrAbortHandler)
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/1", myHandler1)
mux.HandleFunc("/2", myHandler2)
http.ListenAndServe(":8080", mux)
}
When i make a request to the /1 endpoint, on the server i see this:
2021/07/17 09:04:07 http: panic serving [::1]:52336: I panicked
goroutine 4 [running]:
net/http.(*conn).serve.func1(0x1400010aa00)
/usr/local/go/src/net/http/server.go:1824 +0x108
panic(0x102672ca0, 0x1026c3590)
/usr/local/go/src/runtime/panic.go:971 +0x3f4
main.myHandler1(0x1026cbb30, 0x140001420e0, 0x1400014e000)
/Users/echorand/work/github.com/amitsaha/tmp/server.go:6 +0x38
net/http.HandlerFunc.ServeHTTP(0x1026c2790, 0x1026cbb30, 0x140001420e0, 0x1400014e000)
/usr/local/go/src/net/http/server.go:2069 +0x40
net/http.(*ServeMux).ServeHTTP(0x14000024200, 0x1026cbb30, 0x140001420e0, 0x1400014e000)
/usr/local/go/src/net/http/server.go:2448 +0x190
net/http.serverHandler.ServeHTTP(0x14000142000, 0x1026cbb30, 0x140001420e0, 0x1400014e000)
/usr/local/go/src/net/http/server.go:2887 +0xbc
net/http.(*conn).serve(0x1400010aa00, 0x1026cc000, 0x14000024280)
/usr/local/go/src/net/http/server.go:1952 +0x710
created by net/http.(*Server).Serve
/usr/local/go/src/net/http/server.go:3013 +0x308
The recovery is happening here in the stdlib's code:
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
c.remoteAddr = c.rwc.RemoteAddr().String()
ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
defer func() {
if err := recover(); err != nil && err != ErrAbortHandler {
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
}
if !c.hijacked() {
c.close()
c.setState(c.rwc, StateClosed, runHooks)
}
}()
However, when I make a request to the /2 endpoint, there is no log of the panic as explained by the documentation
of ErrAbortHandler
.
Due to the recovery mechanism setup, the server process doesn't get aborted and the panic details are logged.
You can also write a middleware to setup your own recovery mechanism so that the stdlib's recovery mechanism is not triggered at all.