Documentation
¶
Overview ¶
Package middleware provides a collection of HTTP middleware for use with kage or any net/http compatible router. It includes structured logging, panic recovery, and a response writer wrapper that captures the HTTP status code.
Index ¶
- func CORS(cfg CORSConfig) func(http.Handler) http.Handler
- func CacheControl(val string) func(http.Handler) http.Handler
- func Compress(next http.Handler) http.Handler
- func GetRequestID(r *http.Request) string
- func Logger(l *slog.Logger) func(http.Handler) http.Handler
- func NoCache(next http.Handler) http.Handler
- func Recoverer(l *slog.Logger, onFailure func(http.ResponseWriter, *http.Request, any)) func(http.Handler) http.Handler
- func RequestID(next http.Handler) http.Handler
- func Timeout(duration time.Duration, onFailure func(http.ResponseWriter, *http.Request)) func(http.Handler) http.Handler
- type CORSConfig
- type WrapResponseWriter
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CORS ¶ added in v0.5.0
func CORS(cfg CORSConfig) func(http.Handler) http.Handler
CORS returns a middleware that adds Cross-Origin Resource Sharing headers to every response based on the provided configuration.
Preflight requests (OPTIONS) are handled automatically and short-circuited with a 204 No Content response.
Example:
r.Use(middleware.CORS(middleware.DefaultCORSConfig()))
// With specific origins:
r.Use(middleware.CORS(middleware.DefaultCORSConfig("https://myapp.com")))
// Fully custom:
r.Use(middleware.CORS(middleware.CORSConfig{
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET", "POST"},
AllowedHeaders: []string{"Content-Type", "Authorization"},
}))
func CacheControl ¶ added in v0.7.3
CacheControl sets the Cache-Control header on every response.
Example:
r.Use(middleware.CacheControl("no-store"))
r.Use(middleware.CacheControl("public, max-age=3600"))
func Compress ¶ added in v0.6.0
Compress returns a middleware that compresses responses using gzip or deflate based on the client's Accept-Encoding header. If the client does not support compression, the response is passed through unchanged.
func GetRequestID ¶ added in v0.6.0
GetRequestID returns the request ID stored in the context by the RequestID middleware. Returns an empty string if no ID is found.
func Logger ¶
Logger returns a middleware that logs request details using structured logging. If l is nil, it uses the default slog logger.
func NoCache ¶ added in v0.7.3
NoCache sets headers to prevent the response from being cached by browsers or intermediary proxies.
Example:
r.Use(middleware.NoCache)
func Recoverer ¶
func Recoverer(l *slog.Logger, onFailure func(http.ResponseWriter, *http.Request, any)) func(http.Handler) http.Handler
Recoverer returns a middleware that recovers from panics and logs the error.
If onFailure is provided, it is called to write the error response, giving full control over the format (e.g. JSON). The recovered panic value is passed as the third argument. If onFailure is nil, it defaults to 500 Internal Server Error.
Example:
r.Use(middleware.Recoverer(nil, nil))
// With a custom JSON error:
r.Use(middleware.Recoverer(logger, func(w http.ResponseWriter, r *http.Request, err any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
_, _ = fmt.Fprintf(w, `{"error":"%v"}`, err)
}))
func RequestID ¶ added in v0.6.0
RequestID is a middleware that assigns a unique ID to each request. If the incoming request already carries an X-Request-ID header, that value is reused. Otherwise a new random ID is generated. The ID is stored in the request context and set on the response header.
func Timeout ¶ added in v0.5.0
func Timeout(duration time.Duration, onFailure func(http.ResponseWriter, *http.Request)) func(http.Handler) http.Handler
Timeout returns a middleware that cancels the request context after the given duration.
If the timeout expires before the handler writes a response, onFailure is called to write the error response. If onFailure is nil, it defaults to 503 Service Unavailable.
If the handler has already started writing a response before the deadline is reached, the error handler is not called to avoid a duplicate response.
Example:
r.Use(middleware.Timeout(5*time.Second, nil))
// With a custom JSON error:
r.Use(middleware.Timeout(5*time.Second, func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
_, _ = w.Write([]byte(`{"error":"request timeout"}`))
}))
Types ¶
type CORSConfig ¶ added in v0.5.0
type CORSConfig struct {
AllowedOrigins []string
AllowedMethods []string
AllowedHeaders []string
AllowCredentials bool
MaxAge int
}
CORSConfig holds the configuration for the CORS middleware.
func DefaultCORSConfig ¶ added in v0.5.0
func DefaultCORSConfig(origins ...string) CORSConfig
DefaultCORSConfig returns a CORSConfig with permissive defaults suitable for development. Specific origins can be provided to restrict access in production.
Example:
middleware.CORS(middleware.DefaultCORSConfig())
middleware.CORS(middleware.DefaultCORSConfig("https://myapp.com"))
type WrapResponseWriter ¶
type WrapResponseWriter struct {
http.ResponseWriter
// contains filtered or unexported fields
}
WrapResponseWriter is a wrapper around http.WrapResponseWriter that captures the HTTP status code and tracks if headers have been written.
func NewWrapResponseWriter ¶
func NewWrapResponseWriter(w http.ResponseWriter) *WrapResponseWriter
NewWrapResponseWriter creates a new responseWriter with a default status of 200 OK.
func (*WrapResponseWriter) Status ¶
func (rw *WrapResponseWriter) Status() int
Status returns the captured HTTP status code.
func (*WrapResponseWriter) Unwrap ¶
func (rw *WrapResponseWriter) Unwrap() http.ResponseWriter
Unwrap returns the underlying ResponseWriter. This is essential for http.ResponseController to access advanced features like Hijack or Flush through the wrapper.
func (*WrapResponseWriter) Write ¶
func (rw *WrapResponseWriter) Write(b []byte) (int, error)
Write ensures that WriteHeader is called with http.StatusOK if it hasn't been called yet.
func (*WrapResponseWriter) WriteHeader ¶
func (rw *WrapResponseWriter) WriteHeader(code int)
WriteHeader captures the status code and delegates to the underlying ResponseWriter.
func (*WrapResponseWriter) Written ¶
func (rw *WrapResponseWriter) Written() bool
Written returns true if the HTTP response headers have been sent.