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