Files
Nip-05-api/internal/http/middleware/recoverer.go
2026-04-29 02:35:00 +00:00

43 lines
1.1 KiB
Go

package middleware
import (
"encoding/json"
"log/slog"
"net/http"
"runtime/debug"
)
// Recoverer turns panics into 500 JSON responses without leaking the stack to
// clients. The full stack is logged at error level.
func Recoverer(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rv := recover(); rv != nil {
slog.Error("panic recovered",
"path", r.URL.Path,
"method", r.Method,
"err", rv,
"stack", string(debug.Stack()),
)
if !headerWritten(w) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
_ = json.NewEncoder(w).Encode(map[string]string{
"error": "InternalError",
"detail": "internal server error",
})
}
}
}()
next.ServeHTTP(w, r)
})
}
// headerWritten is best-effort; if the response is hijacked we skip writing.
func headerWritten(w http.ResponseWriter) bool {
if rw, ok := w.(interface{ Status() int }); ok {
return rw.Status() != 0
}
return false
}