Documentation
¶
Overview ¶
Package recovery provides panic recovery middleware for celeris.
The middleware catches panics from downstream handlers, logs the stack trace via slog, and returns a configurable error response instead of crashing the server.
Basic usage with defaults (4 KB stack trace, JSON 500 response):
server.Use(recovery.New())
Custom error handler and stack size:
server.Use(recovery.New(recovery.Config{
StackSize: 8192,
ErrorHandler: func(c *celeris.Context, err any) error {
return c.String(500, "Something went wrong")
},
}))
Set Config.StackSize to 0 to disable stack trace capture (the panic value, method, and path are still logged). Set Config.DisableLogStack to true to suppress panic logging entirely.
Special Panic Types ¶
Panics with http.ErrAbortHandler are re-panicked rather than recovered, preserving the standard library's abort semantics.
Broken pipe and ECONNRESET errors are detected automatically and logged at WARN level without a stack trace. Use Config.BrokenPipeHandler to customize the response for these cases.
Nested Recovery ¶
If Config.ErrorHandler itself panics, the middleware falls back to a default 500 Internal Server Error response.
Log Level ¶
Set Config.LogLevel to control the slog level for normal panic log entries (default: slog.LevelError). Broken pipe panics are always logged at slog.LevelWarn regardless of this setting.
Sentinel Errors ¶
The package exports sentinel errors for use with errors.Is:
- ErrPanic: generic panic recovery
- ErrBrokenPipe: broken pipe or ECONNRESET
- ErrPanicContextCancelled: panic after the request context was cancelled
- ErrPanicResponseCommitted: panic after the response has been committed
Middleware Order ¶
Register after logger/metrics so they see the 500 status from recovered panics.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrPanic is the base sentinel for all recovery-caught panics. ErrPanic = errors.New("recovery: panic") // ErrPanicContextCancelled is returned when a panic occurs after // the request context has been cancelled. ErrPanicContextCancelled = errors.New("recovery: panic (context cancelled)") // ErrPanicResponseCommitted is returned when a panic occurs after // the response has already been partially written. ErrPanicResponseCommitted = errors.New("recovery: panic (response committed)") // ErrBrokenPipe is returned when a panic is caused by a broken pipe // or connection reset (client disconnected). ErrBrokenPipe = errors.New("recovery: broken pipe") )
Functions ¶
func New ¶
func New(config ...Config) celeris.HandlerFunc
New creates a recovery middleware with the given config.
Example ¶
package main
import (
"github.com/goceleris/celeris/middleware/recovery"
)
func main() {
// Zero-config: catches panics, logs stack trace, returns 500 JSON.
_ = recovery.New()
}
Output:
Example (CustomHandler) ¶
package main
import (
"github.com/goceleris/celeris"
"github.com/goceleris/celeris/middleware/recovery"
)
func main() {
// Custom error handler for panics.
_ = recovery.New(recovery.Config{
ErrorHandler: func(c *celeris.Context, err any) error {
return c.String(500, "something went wrong: %v", err)
},
})
}
Output:
Example (StackAll) ¶
package main
import (
"github.com/goceleris/celeris/middleware/recovery"
)
func main() {
// Capture all goroutine stacks (not just the panicking one).
_ = recovery.New(recovery.Config{
StackAll: true,
StackSize: 8192,
})
}
Output:
Types ¶
type Config ¶
type Config struct {
// Skip defines a function to skip this middleware for certain requests.
Skip func(c *celeris.Context) bool
// SkipPaths is a list of request paths to exclude from recovery.
// Matching is exact (no glob or prefix support).
SkipPaths []string
// ErrorHandler handles the recovered panic value. Default: JSON 500 response.
//
// Prefer [ErrorHandlerErr] for new code: it receives a concrete
// error value (panic-value-as-error wrapped if necessary), which
// matches the pattern used by jwt/keyauth/basicauth/csrf and
// supports errors.Is / errors.As. ErrorHandler is retained for
// backwards compatibility; if both are set, ErrorHandlerErr wins.
ErrorHandler func(c *celeris.Context, err any) error
// ErrorHandlerErr is the error-typed counterpart of [ErrorHandler]
// added in v1.3.4 to align with the rest of the auth middleware
// family. The middleware wraps non-error panic values with
// fmt.Errorf("recovery: panic: %v", r) before invocation.
ErrorHandlerErr func(c *celeris.Context, err error) error
// BrokenPipeHandler handles broken pipe / connection reset panics.
// When nil, broken pipe panics are logged at WARN level without a stack
// trace and the middleware returns a descriptive error.
BrokenPipeHandler func(c *celeris.Context, err any) error
// StackSize is the max bytes for stack trace capture. Default: 4096.
// Set to 0 to disable stack capture (panic value, method, and path
// are still logged). Negative values are silently replaced with the default.
StackSize int
// DisableLogStack disables all panic logging on recovery. When true,
// panics are still caught and the error handler is called, but no log
// entry is emitted. Default: false (panics are logged with stack traces).
DisableLogStack bool
// StackAll captures all goroutine stacks, not just the current one.
// Default: false (current goroutine only).
StackAll bool
// DisableBrokenPipeLog suppresses the WARN-level log for broken pipe
// and ECONNRESET panics. Default: false (log enabled).
DisableBrokenPipeLog bool
// Logger is the slog logger for panic logging. Default: slog.Default().
Logger *slog.Logger
// LogLevel is the slog level used for normal panic log entries.
// Default: slog.LevelError. Broken pipe panics are always logged
// at slog.LevelWarn regardless of this setting.
LogLevel slog.Level
}
Config defines the recovery middleware configuration.