package httpmw import ( "context" "net/http" "runtime/debug" "cdr.dev/slog" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/tracing" ) func Recover(log slog.Logger) func(h http.Handler) http.Handler { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { r := recover() // Reverse proxying (among other things) may panic with // http.ErrAbortHandler when the request is aborted. It's not a // real panic so we shouldn't log them. // //nolint:errorlint // this is how the stdlib does the check if r != nil && r != http.ErrAbortHandler { log.Warn(context.Background(), "panic serving http request (recovered)", slog.F("panic", r), slog.F("stack", string(debug.Stack())), ) var hijacked bool if sw, ok := w.(*tracing.StatusWriter); ok { hijacked = sw.Hijacked } // Only try to write errors on // non-hijacked responses. if !hijacked { httpapi.InternalServerError(w, nil) } } }() h.ServeHTTP(w, r) }) } }