github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/middlewares/recover.go (about) 1 package middlewares 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 "runtime" 8 9 "github.com/cozy/cozy-stack/pkg/logger" 10 "github.com/labstack/echo/v4" 11 "github.com/labstack/echo/v4/middleware" 12 ) 13 14 // RecoverConfig defines the config for Recover middleware. 15 type RecoverConfig struct { 16 // Skipper defines a function to skip middleware. 17 Skipper middleware.Skipper 18 19 // Size of the stack to be printed. 20 // Optional. Default value 4KB. 21 StackSize int `json:"stack_size"` 22 } 23 24 // RecoverWithConfig returns a Recover middleware with config. 25 func RecoverWithConfig(config RecoverConfig) echo.MiddlewareFunc { 26 // Defaults 27 if config.Skipper == nil { 28 config.Skipper = middleware.DefaultSkipper 29 } 30 if config.StackSize == 0 { 31 config.StackSize = 4 << 10 // 4 KB 32 } 33 34 return func(next echo.HandlerFunc) echo.HandlerFunc { 35 return func(c echo.Context) error { 36 if config.Skipper(c) { 37 return next(c) 38 } 39 40 defer func() { 41 if r := recover(); r != nil { 42 var err error 43 switch r := r.(type) { 44 case error: 45 err = r 46 default: 47 err = fmt.Errorf("%v", r) 48 } 49 // We don't want to log panic with ErrAbortHandler, as it 50 // is just noise (http.Server does that too). 51 // See https://golang.org/pkg/net/http/#ErrAbortHandler 52 if !errors.Is(err, http.ErrAbortHandler) { 53 stack := make([]byte, config.StackSize) 54 length := runtime.Stack(stack, false) 55 log := logger.WithDomain(c.Request().Host).WithField("panic", true) 56 log.Errorf("PANIC RECOVER %s: %s", err.Error(), stack[:length]) 57 c.Error(err) 58 } 59 } 60 }() 61 return next(c) 62 } 63 } 64 }