Documentation
¶
Overview ¶
Package middleware provides HTTP middleware for use with go-httpkit and chi.
Client IP ¶
ClientIP resolves the client IP (using trusted proxy CIDRs for X-Real-IP and X-Forwarded-For) and stores it in the request context. CIDRs are parsed once at build time. Use GetClientIPFromContext in handlers to read it. Returns an error if all CIDR entries are invalid; empty or nil slice means no proxy trust.
Logging ¶
Logger logs each request (method, path, redacted query, IP, user-agent, request_id) and after the handler adds status, latency_ms, and bytes. Log level: Info for 2xx, Warn for 4xx, Error for 5xx. Sensitive query params (token, password, etc.) are redacted. If log is nil, the middleware is a no-op. CIDRs are parsed once at build time.
Metrics ¶
Metrics records http_requests_total and http_request_duration_seconds (Prometheus). Pass a PathFromRequest that returns route patterns (e.g. httputil.ChiPathFromRequest), not raw paths, to avoid unbounded label cardinality. reg can be nil for DefaultRegisterer. Optional logger for registration errors.
Recoverer ¶
Recoverer recovers panics, logs the panic and stack trace (if log is non-nil), and responds with 500 JSON. Place it at the top of the middleware chain.
Request ID ¶
RequestID sets or propagates X-Request-ID (from header or new UUID), validates format to prevent response splitting, and stores it in context. Use GetRequestID to read it.
Security headers ¶
SecurityHeaders sets X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, Content-Security-Policy, and optionally Strict-Transport-Security (HSTS). Set addHSTS true for HTTPS. style-src is 'self'.
Timeout ¶
Timeout runs the handler with a context deadline. On timeout it responds with 503 JSON. The full response body is buffered in memory—do not use for streaming or large responses. TimeoutWithLimit adds a max response body size; when exceeded the response is truncated and ErrResponseBodyTooLarge is returned. The handler goroutine may continue after the response; handlers should check context cancellation.
Index ¶
- Variables
- func ClientIP(trustedProxyCIDRs []string) (func(http.Handler) http.Handler, error)
- func GetClientIPFromContext(ctx context.Context) string
- func GetRequestID(ctx context.Context) string
- func Logger(log logger.Logger, trustedProxyCIDRs []string) func(next http.Handler) http.Handler
- func Metrics(reg prometheus.Registerer, pathFromRequest PathFromRequest, ...) func(http.Handler) http.Handler
- func Recoverer(log logger.Logger) func(http.Handler) http.Handler
- func RequestID() func(http.Handler) http.Handler
- func SecurityHeaders(addHSTS bool) func(http.Handler) http.Handler
- func Timeout(d time.Duration, log ...logger.Logger) func(http.Handler) http.Handler
- func TimeoutWithLimit(d time.Duration, maxResponseBytes int64, log ...logger.Logger) func(http.Handler) http.Handler
- type PathFromRequest
Constants ¶
This section is empty.
Variables ¶
var ErrResponseBodyTooLarge = errors.New("response body size limit exceeded")
ErrResponseBodyTooLarge is returned by timeoutWriter.Write when the buffered response body would exceed the configured maxResponseBytes.
Functions ¶
func ClientIP ¶ added in v0.1.4
ClientIP returns middleware that resolves the client IP (using trustedProxyCIDRs for X-Real-IP and X-Forwarded-For) and stores it in the request context. CIDRs are parsed once at build time. Returns an error if all entries are invalid; empty or nil slice is valid (no proxy trust).
func GetClientIPFromContext ¶ added in v0.1.4
GetClientIPFromContext returns the client IP stored by the ClientIP middleware, or "" if not set.
func GetRequestID ¶ added in v0.1.3
GetRequestID returns the request ID from the context (set by RequestID middleware), or "" if not set.
func Logger ¶ added in v0.1.4
Logger returns middleware that logs each request (method, path, redacted query, IP, user-agent, request_id) and after the handler adds status, latency_ms, bytes, logging at Info (2xx), Warn (4xx), or Error (5xx). Sensitive query params are redacted. If log is nil, passes through without logging. Invalid trustedProxyCIDRs are logged at Warn once at build time.
func Metrics ¶
func Metrics(reg prometheus.Registerer, pathFromRequest PathFromRequest, logger ...metricsLogger) func(http.Handler) http.Handler
Metrics returns middleware that records http_requests_total and http_request_duration_seconds. reg can be nil for DefaultRegisterer. pathFromRequest can be nil. Optional logger for registration errors; if nil, log.Default() is used.
func Recoverer ¶ added in v0.1.3
Recoverer returns middleware that recovers panics, logs the panic and stack trace (if log is non-nil), and responds with 500 JSON. Place at the top of the chain.
func RequestID ¶ added in v0.1.3
RequestID returns middleware that sets X-Request-ID from the request header or generates a new UUID, and stores it in the context. Invalid header values are replaced with a new UUID to prevent response splitting.
func SecurityHeaders ¶ added in v0.1.3
SecurityHeaders returns middleware that sets common security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, Content-Security-Policy). If addHSTS is true, adds Strict-Transport-Security (max-age=2 years, includeSubDomains, preload). Set addHSTS for HTTPS-only services.
func Timeout ¶ added in v0.1.3
Timeout returns middleware that runs the handler with a context deadline of d. If the deadline is exceeded, responds with 503 JSON. The response body is buffered in memory—do not use for streaming or large responses. The handler may keep running after the response; it should respect context cancellation. After sending the timeout response, the middleware waits up to timeoutGracePeriod for the handler to finish; if the handler does not complete in that time, its goroutine may still be running—handlers should check ctx.Done() to exit promptly, and operators should monitor for goroutine leaks. Optional log is used to log recovered panics (panic value and stack) from the handler goroutine.
func TimeoutWithLimit ¶ added in v0.1.4
func TimeoutWithLimit(d time.Duration, maxResponseBytes int64, log ...logger.Logger) func(http.Handler) http.Handler
TimeoutWithLimit is like Timeout but rejects response body writes when total buffered size would exceed maxResponseBytes (0 = unlimited). Optional log is used to log recovered panics.
Types ¶
type PathFromRequest ¶
PathFromRequest returns the route pattern for the request (e.g. from chi.RouteContext). Used by Metrics for the path label. Must return a stable pattern like "/users/{id}", not the raw path, to avoid unbounded Prometheus cardinality. If the function is nil, path is "/unknown" or "/not-found" for 404.