testgo1/pkg/middleware/recovery.go
jordan 7a71cc0e8f
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/manual/woodpecker Pipeline was successful
Initialize project from skeleton template
2026-02-01 20:31:42 +00:00

55 lines
1.5 KiB
Go

package middleware
import (
"net/http"
"runtime/debug"
"github.com/jordan/testgo1/pkg/httpcontext"
"github.com/jordan/testgo1/pkg/logging"
)
// Recoverer is middleware that recovers from panics, logs the error with stack trace
// using slog, and returns a 500 Internal Server Error response.
//
// The middleware captures:
// - request_id: For request correlation
// - method, path, remote_addr: Request context
// - panic: The recovered panic value
// - stack_trace: Full stack trace for debugging
//
// Usage:
//
// r.Use(middleware.RequestID())
// r.Use(middleware.RequestLogger(logger))
// r.Use(middleware.Recoverer(logger))
func Recoverer(logger *logging.Logger) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rvr := recover(); rvr != nil {
// Capture stack trace for debugging
stack := debug.Stack()
// Get request ID from context
requestID, _ := httpcontext.GetRequestID(r.Context())
// Log panic with full context and stack trace
logger.Error("panic recovered",
"request_id", requestID,
"method", r.Method,
"path", r.URL.Path,
"remote_addr", r.RemoteAddr,
"panic", rvr,
"stack_trace", string(stack),
)
// Return 500 Internal Server Error to client
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}
}