Documentation
¶
Overview ¶
Package middleware provides production-ready HTTP middleware that works with any net/http compatible router.
All middleware follows the standard func(http.Handler) http.Handler signature.
Usage:
stack := middleware.Chain(
middleware.RequestID(),
middleware.Logger(logger),
middleware.Recover(),
middleware.CORS(middleware.DefaultCORSConfig()),
middleware.Timeout(30 * time.Second),
)
http.ListenAndServe(":8080", stack(mux))
Index ¶
- func GetAuthUser(ctx context.Context) any
- func GetAuthUserAs[T any](ctx context.Context) (T, bool)
- func GetRequestID(ctx context.Context) string
- func Then(handler http.Handler, middlewares ...Middleware) http.Handler
- type AuthConfig
- type CORSConfig
- type LoggerConfig
- type Middleware
- func Auth(cfg AuthConfig) Middleware
- func BodyLimit(maxBytes int64) Middleware
- func CORS(cfg CORSConfig) Middleware
- func Chain(middlewares ...Middleware) Middleware
- func Logger(logger *slog.Logger) Middleware
- func LoggerWithConfig(cfg LoggerConfig) Middleware
- func RateLimit(cfg RateLimitConfig) Middleware
- func Recover() Middleware
- func RecoverWithConfig(cfg RecoverConfig) Middleware
- func RequestID() Middleware
- func RequestIDWithConfig(cfg RequestIDConfig) Middleware
- func RequireRole(role string, roleExtractor func(ctx context.Context) []string) Middleware
- func SecureHeaders() Middleware
- func SecureHeadersWithConfig(cfg SecurityHeadersConfig) Middleware
- func Timeout(duration time.Duration) Middleware
- type RateLimitConfig
- type RateLimiter
- type RecoverConfig
- type RequestIDConfig
- type SecurityHeadersConfig
- type TokenBucket
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAuthUser ¶
GetAuthUser retrieves the authenticated user from the request context. Returns nil if no user is set.
func GetAuthUserAs ¶
GetAuthUserAs retrieves the authenticated user with type assertion.
user, ok := middleware.GetAuthUserAs[*User](r.Context())
func GetRequestID ¶
GetRequestID retrieves the request ID from the context.
Types ¶
type AuthConfig ¶
type AuthConfig struct {
// Authenticate is the function that validates credentials and returns user info.
// The token/key string is extracted from the request based on the scheme.
// Return any user object to store in context, or error to reject.
Authenticate func(ctx context.Context, token string) (any, error)
// Scheme determines where to extract credentials from.
// Default: "bearer"
// Options: "bearer", "api-key"
Scheme string
// APIKeyHeader is the header name for API key auth.
// Default: "X-API-Key"
APIKeyHeader string
// SkipPaths are paths that bypass authentication.
SkipPaths map[string]bool
// ErrorMessage is the message for unauthorized responses.
// Default: "Authentication required"
ErrorMessage string
}
AuthConfig configures authentication middleware.
type CORSConfig ¶
type CORSConfig struct {
// AllowOrigins is a list of allowed origins.
// Use "*" to allow all origins (not recommended for production with credentials).
// Default: []
AllowOrigins []string
// AllowMethods is a list of allowed HTTP methods.
// Default: GET, POST, PUT, PATCH, DELETE, OPTIONS
AllowMethods []string
// AllowHeaders is a list of allowed request headers.
// Default: Content-Type, Authorization, X-Request-ID
AllowHeaders []string
// ExposeHeaders is a list of headers the browser is allowed to access.
// Default: X-Request-ID
ExposeHeaders []string
// AllowCredentials indicates whether credentials (cookies, auth headers) are allowed.
// Default: false
AllowCredentials bool
// MaxAge is how long preflight results can be cached.
// Default: 12 hours
MaxAge time.Duration
}
CORSConfig configures the CORS middleware.
func DefaultCORSConfig ¶
func DefaultCORSConfig() CORSConfig
DefaultCORSConfig returns a permissive CORS configuration for development. For production, you should specify AllowOrigins explicitly.
type LoggerConfig ¶
type LoggerConfig struct {
// Logger is the slog.Logger to use. Default: slog.Default()
Logger *slog.Logger
// Level is the default log level for successful requests. Default: slog.LevelInfo
Level slog.Level
// SkipPaths is a set of paths to skip logging for (e.g., health checks).
SkipPaths map[string]bool
// LogRequestBody logs the request body (use with caution — PII concerns).
// Default: false
LogRequestBody bool
// LogResponseBody logs the response body.
// Default: false
LogResponseBody bool
}
LoggerConfig configures the Logger middleware.
func DefaultLoggerConfig ¶
func DefaultLoggerConfig() LoggerConfig
DefaultLoggerConfig returns the default logger configuration.
type Middleware ¶
Middleware is a function that wraps an http.Handler.
func Auth ¶
func Auth(cfg AuthConfig) Middleware
Auth creates an authentication middleware.
Example with bearer token:
auth := middleware.Auth(middleware.AuthConfig{
Authenticate: func(ctx context.Context, token string) (any, error) {
user, err := verifyJWT(token)
if err != nil { return nil, errors.Unauthorized("Invalid token") }
return user, nil
},
SkipPaths: map[string]bool{"/health": true, "/login": true},
})
func BodyLimit ¶
func BodyLimit(maxBytes int64) Middleware
BodyLimit limits the maximum request body size. Requests exceeding the limit receive a 413 Payload Too Large response.
mux.Handle("/upload", middleware.BodyLimit(10<<20)(handler)) // 10 MB
func Chain ¶
func Chain(middlewares ...Middleware) Middleware
Chain composes multiple middleware into a single middleware. Middleware is applied in the order provided (first middleware is outermost).
stack := middleware.Chain(first, second, third) // Request flow: first → second → third → handler // Response flow: third → second → first → client
func Logger ¶
func Logger(logger *slog.Logger) Middleware
Logger logs each HTTP request with structured fields. Logs: method, path, status, duration, request_id, client_ip, user_agent.
func LoggerWithConfig ¶
func LoggerWithConfig(cfg LoggerConfig) Middleware
LoggerWithConfig creates a logging middleware with custom configuration.
func RateLimit ¶
func RateLimit(cfg RateLimitConfig) Middleware
RateLimit applies rate limiting per client.
func Recover ¶
func Recover() Middleware
Recover recovers from panics and returns a 500 JSON response. Internal error details are logged but NOT exposed to clients.
func RecoverWithConfig ¶
func RecoverWithConfig(cfg RecoverConfig) Middleware
RecoverWithConfig recovers from panics with custom configuration.
func RequestID ¶
func RequestID() Middleware
RequestID adds a unique request ID to each request. The ID is stored in the request context and set as a response header.
func RequestIDWithConfig ¶
func RequestIDWithConfig(cfg RequestIDConfig) Middleware
RequestIDWithConfig adds request IDs with custom configuration.
func RequireRole ¶
func RequireRole(role string, roleExtractor func(ctx context.Context) []string) Middleware
RequireRole creates middleware that checks if the authenticated user has a required role. The roleExtractor function should return the user's roles from the context.
func SecureHeaders ¶
func SecureHeaders() Middleware
SecureHeaders adds security headers to responses.
func SecureHeadersWithConfig ¶
func SecureHeadersWithConfig(cfg SecurityHeadersConfig) Middleware
SecureHeadersWithConfig adds security headers with custom configuration.
func Timeout ¶
func Timeout(duration time.Duration) Middleware
Timeout wraps each request with a context deadline. If the handler doesn't complete within the timeout, a 504 response is sent.
mux.Handle("/slow", middleware.Timeout(5*time.Second)(handler))
type RateLimitConfig ¶
type RateLimitConfig struct {
// Limiter is the rate limiting backend.
// If nil, a default in-memory token bucket is used.
Limiter RateLimiter
// KeyFunc extracts the rate limit key from the request.
// Default: uses client IP from RemoteAddr (safe).
// Set TrustProxy to true if behind a reverse proxy.
KeyFunc func(r *http.Request) string
// TrustProxy enables reading client IP from X-Forwarded-For and X-Real-IP headers.
// Only enable this if your server is behind a trusted reverse proxy.
// Default: false (uses RemoteAddr only)
TrustProxy bool
// Rate is the number of requests allowed per window (for default limiter).
// Default: 100
Rate int
// Window is the time window for the rate limit (for default limiter).
// Default: 1 minute
Window time.Duration
// Message is the error message sent when rate limited.
// Default: "Rate limit exceeded"
Message string
}
RateLimitConfig configures the rate limiting middleware.
func DefaultRateLimitConfig ¶
func DefaultRateLimitConfig() RateLimitConfig
DefaultRateLimitConfig returns sensible rate limit defaults.
type RateLimiter ¶
type RateLimiter interface {
// Allow checks if a request from the given key is allowed.
// Returns true if allowed, false if rate limited.
Allow(key string) bool
}
RateLimiter defines the interface for rate limiting backends. Implement this interface to use Redis, memcached, etc.
type RecoverConfig ¶
type RecoverConfig struct {
// Logger is used to log panic details.
// If nil, uses slog.Default().
Logger *slog.Logger
// EnableStackTrace includes the stack trace in logs.
// Default: true
EnableStackTrace bool
// OnPanic is called when a panic is recovered.
// If nil, a default handler is used.
OnPanic func(w http.ResponseWriter, r *http.Request, recovered any)
}
RecoverConfig configures the Recover middleware.
func DefaultRecoverConfig ¶
func DefaultRecoverConfig() RecoverConfig
DefaultRecoverConfig returns the default configuration.
type RequestIDConfig ¶
type RequestIDConfig struct {
// Header is the header to read/write the request ID.
// Default: "X-Request-ID"
Header string
// Generator is a function that generates a new request ID.
// Default: generates a random 16-byte hex string.
Generator func() string
// TrustProxy trusts the incoming X-Request-ID header if present.
// If false, always generates a new ID.
// Default: true
TrustProxy bool
}
RequestIDConfig configures the RequestID middleware.
func DefaultRequestIDConfig ¶
func DefaultRequestIDConfig() RequestIDConfig
DefaultRequestIDConfig returns the default configuration.
type SecurityHeadersConfig ¶
type SecurityHeadersConfig struct {
// ContentTypeNosniff sets X-Content-Type-Options: nosniff
// Default: true
ContentTypeNosniff bool
// XFrameOptions sets X-Frame-Options. Common values: DENY, SAMEORIGIN
// Default: "DENY"
XFrameOptions string
// XSSProtection sets X-XSS-Protection.
// Default: "1; mode=block"
XSSProtection string
// HSTSMaxAge sets Strict-Transport-Security max-age in seconds.
// Set to 0 to disable. Default: 31536000 (1 year)
HSTSMaxAge int
// HSTSIncludeSubdomains adds includeSubDomains to HSTS.
// Default: true
HSTSIncludeSubdomains bool
// ReferrerPolicy sets Referrer-Policy header.
// Default: "strict-origin-when-cross-origin"
ReferrerPolicy string
// ContentSecurityPolicy sets Content-Security-Policy header.
// Default: "" (not set)
ContentSecurityPolicy string
// PermissionsPolicy sets Permissions-Policy header.
// Default: "" (not set)
PermissionsPolicy string
}
SecurityHeadersConfig configures security headers.
func DefaultSecurityHeadersConfig ¶
func DefaultSecurityHeadersConfig() SecurityHeadersConfig
DefaultSecurityHeadersConfig returns recommended security headers.
type TokenBucket ¶
type TokenBucket struct {
// contains filtered or unexported fields
}
TokenBucket implements a simple in-memory token bucket rate limiter.
func NewTokenBucket ¶
func NewTokenBucket(rate int, window time.Duration) *TokenBucket
NewTokenBucket creates a new in-memory token bucket rate limiter. Call Stop() when the limiter is no longer needed to release the cleanup goroutine.
func (*TokenBucket) Allow ¶
func (tb *TokenBucket) Allow(key string) bool
Allow checks if a request is allowed for the given key.
func (*TokenBucket) Stop ¶
func (tb *TokenBucket) Stop()
Stop terminates the background cleanup goroutine. The TokenBucket should not be used after calling Stop.