package middleware import ( "fmt" "log/slog" "net/http" "go.bigb.es/auxilia/culpa" "go.bigb.es/auxilia/scribe" ) // Recovery catches panics from downstream handlers, logs them with a stack // trace via culpa, and returns a generic 500 so a single bad handler can't // crash the process. func Recovery(logger *slog.Logger) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if rec := recover(); rec != nil { err, ok := rec.(error) if !ok { err = fmt.Errorf("%v", rec) } err = culpa.Wrap(err, "panic recovered") logger.Error("panic recovered", "path", r.URL.Path, scribe.Err(err), ) http.Error(w, "internal server error", http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } }