32 lines
890 B
Go
32 lines
890 B
Go
|
|
package middleware
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"log/slog"
|
|||
|
|
"net/http"
|
|||
|
|
"runtime/debug"
|
|||
|
|
|
|||
|
|
"github.com/gin-gonic/gin"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// Recovery перехватывает панику в хендлере: клиент получает честный
|
|||
|
|
// 500 с фиксированным текстом, а в лог уходят причина и стек —
|
|||
|
|
// стек наружу не уходит, но без него панику не воспроизвести.
|
|||
|
|
func Recovery() gin.HandlerFunc {
|
|||
|
|
return func(c *gin.Context) {
|
|||
|
|
defer func() {
|
|||
|
|
if rec := recover(); rec != nil {
|
|||
|
|
slog.Error("panic recovered",
|
|||
|
|
"error", rec,
|
|||
|
|
"request_id", RequestIDFrom(c),
|
|||
|
|
"method", c.Request.Method,
|
|||
|
|
"path", c.Request.URL.Path,
|
|||
|
|
"stack", string(debug.Stack()),
|
|||
|
|
)
|
|||
|
|
c.AbortWithStatusJSON(http.StatusInternalServerError,
|
|||
|
|
gin.H{"error": "internal server error"})
|
|||
|
|
}
|
|||
|
|
}()
|
|||
|
|
c.Next()
|
|||
|
|
}
|
|||
|
|
}
|