package web import ( "net" "net/http" "strings" "time" "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" ) func LoggingMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() c.Next() log.Info(). Str("method", c.Request.Method). Str("path", c.Request.URL.Path). Int("status", c.Writer.Status()). Dur("latency", time.Since(start)). Msg("Request") } } func RecoveryMiddleware() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if r := recover(); r != nil { // Don't log broken pipe errors — client disconnected. if err, ok := r.(error); ok { if ne, ok := err.(*net.OpError); ok && ne.Op == "write" { if strings.Contains(ne.Err.Error(), "broken pipe") || strings.Contains(ne.Err.Error(), "connection reset") { c.Abort() return } } } log.Error().Interface("panic", r).Str("path", c.Request.URL.Path).Msg("Recovery from panic") c.AbortWithStatus(http.StatusInternalServerError) } }() c.Next() } }