middleware

package
v0.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 17, 2026 License: MIT Imports: 21 Imported by: 0

README

http/middleware

中文

Optional standard func(http.Handler) http.Handler middleware. Inject these into routes.HandlerOptions.Middleware, attach endpoint-only policies through Blueprint, or use them with any net/http router. Constructors do not install themselves.

Application middleware

handler, err := routes.NewHandler(root.Routes(), routes.HandlerOptions{
	Middleware: []routes.Middleware{
		middleware.RequestID,
		middleware.AccessLog(middleware.AccessLogOptions{Logger: logger}),
		middleware.CORS(middleware.CORSOptions{
			AllowedOrigins:   []string{"https://app.example.com"},
			AllowedMethods:   []string{"GET", "POST", "DELETE"},
			AllowedHeaders:   []string{"Authorization", "Content-Type"},
			AllowCredentials: true,
			MaxAge:           5 * time.Minute,
		}),
		middleware.Compress(middleware.CompressOptions{MinSize: 500}),
		middleware.Recover(middleware.RecoverOptions{Logger: logger}),
	},
})
if err != nil {
	return err
}

The list runs from top to bottom on entry and in reverse on exit. Request IDs precede logging; recovery inside compression lets panic responses use the same encoder. An outer middleware's own panic is outside an inner Recover. CORS preflight requests may finish before reaching compression, recovery, or endpoints. Put policies that must cover preflight before CORS.

Request IDs and logging

RequestID delegates to chi's request ID middleware. It accepts the incoming X-Request-Id (or chi's configured request ID header), otherwise generates an ID. It sets context only, not a response header. Read it with RequestIDFromContext(ctx); missing or nil context returns "". Incoming IDs are correlation labels, not trusted identities.

AccessLog uses the same context and logs status, elapsed milliseconds, method, path, and client details through slog. A nil logger disables access logging. Skip and MinLevel control output; forwarded client addresses require configured trusted proxies.

Access logs are also emitted when a handler exits through panic, including http.ErrAbortHandler. These records use error level and include aborted: true. The status is the observed final status, or 0 if no final status was observed; a panic does not invent a 500 or a 200. Ordinary responses keep their existing fields and levels. Skip and MinLevel apply to aborted records too; Skip may therefore receive status 0. Panics propagate unchanged.

Panic recovery

Recover(RecoverOptions{Logger: logger, OnPanic: failureHandler}) logs the panic value and stack. Nil Logger selects slog.Default() at construction. Nil OnPanic returns a plain-text 500 without panic details. A custom handler owns its response status and body.

Use OnPanic: response.InternalServerError() for a JSON 500 response. Presets and custom handler examples are in http/response.

Before invoking OnPanic, recovery clears the pending Content-Length so the failure body can have a different size. Other headers remain available to the handler.

Recovery covers the serving goroutine only. Once the response has started, it re-panics with http.ErrAbortHandler to abort the request instead of appending an error body. It closes a hijacked connection on panic and passes through http.ErrAbortHandler without logging. Flushing, connection hijacking, and response-controller capabilities remain available through the wrapper. Recovery does not buffer responses.

CORS

CORS(CORSOptions{...}) uses rs/cors and handles preflight before routing, including for unregistered paths. It adds permission headers to ordinary responses, including errors. A disallowed origin does not receive permission headers; CORS does not authenticate requests or prevent non-browser clients from reaching handlers.

Option Default and behavior
AllowedOrigins Empty denies all origins. Exact origins and patterns containing one * are supported. Explicit "*" allows every origin.
AllowedMethods GET, HEAD, POST. List methods explicitly.
AllowedHeaders Accept, Content-Type, X-Requested-With. "*" allows all requested headers.
ExposedHeaders No additional exposed headers.
AllowCredentials False. Combining true with a "*" origin panics at construction.
MaxAge Zero leaves the browser's preflight cache default. Positive durations are truncated to seconds; negative durations panic.

Configuration slices are copied during construction. No dynamic configuration registry or global CORS policy is installed.

Compression

Compress(CompressOptions{...}) uses klauspost/compress/gzhttp for gzip response compression. Level accepts -2, -1, or 1–9; zero chooses the default compression level. MinSize is in bytes; zero chooses 1024. Negative sizes and invalid levels panic during construction.

ContentTypes optionally restricts compression to explicit MIME types. Empty uses gzhttp's default filter, which excludes common compressed audio, video, and archive formats. Invalid MIME types and wildcards panic. Parameters are supported: text/plain also matches text/plain; charset=utf-8.

Compression respects gzip negotiation, skips HEAD, already encoded responses, and content ranges, and adds Vary: Accept-Encoding. Compressed responses lose their original ETag and Content-Length. Zstd and request decompression are not enabled. Only the initial threshold/detection buffer is retained, rather than the entire response; flushing and connection hijacking are supported.

Other middleware

  • LimitBody(maxBytes) wraps the body with http.MaxBytesReader when the limit is positive. It does not pre-read or automatically return 413; the body consumer handles the error.
  • RequireJSONBody requires application/json for a nonempty body. Valid media-type parameters and whitespace are accepted; malformed parameters receive 415. Attach it to endpoints that decode JSON.
  • RateLimit(RateLimitOptions{...}) accepts an application key function and OnLimit response callback. IP keys can use configured trusted proxies.

API prefixes, cache policies, body limits, and error formats belong to the application. Inject failure handlers through routes.HandlerOptions; routes.NewHandler sets Allow before invoking the application's 405 handler. See complete HTTP handler for boundary injection and SPA fallback.

Documentation

Overview

Package middleware provides reusable HTTP middleware. Package middleware 提供可复用 HTTP 中间件。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AccessLog

func AccessLog(opts AccessLogOptions) func(http.Handler) http.Handler

AccessLog logs requests with method, path, status, and latency. Aborted requests include aborted=true and status=0 when no final status was observed. Panics propagate unchanged. Skip and MinLevel also apply to aborted requests. AccessLog 记录请求的 method、path、status 和 latency。 中止请求包含 aborted=true;未观察到最终状态时 status=0。 panic 原样传播;Skip 和 MinLevel 同样适用于中止请求。

Example / 示例:

r.Use(middleware.AccessLog(middleware.AccessLogOptions{Logger: logger}))

func CORS added in v0.4.2

func CORS(opts CORSOptions) func(http.Handler) http.Handler

CORS handles preflight requests before routing and adds CORS response headers. Rejected requests receive no access permission headers; this is not authentication. Panics for negative MaxAge or '*' origins combined with credentials. CORS 在路由匹配前处理预检请求,并添加 CORS 响应头。 被拒绝的请求不获得访问许可响应头;这不是认证机制。 MaxAge 为负数或将 '*' 来源与凭证组合使用时 panic。

func Compress added in v0.4.2

func Compress(opts CompressOptions) func(http.Handler) http.Handler

Compress negotiates gzip without buffering the entire response. It preserves flushing and hijacking, skips HEAD and already encoded responses, and removes ETag when compressing. Invalid options panic at construction. Compress 协商 gzip 压缩,不缓存完整响应。 保留刷新和连接接管能力,跳过 HEAD 和已编码响应,压缩时移除 ETag。 配置无效时在构造阶段 panic。

func LimitBody

func LimitBody(maxBytes int64) func(http.Handler) http.Handler

LimitBody sets http.MaxBytesReader when maxBytes > 0. Call LimitBody before decoding the request body. LimitBody 在 maxBytes > 0 时设置 http.MaxBytesReader。 在解码请求体前调用 LimitBody。

func RateLimit

func RateLimit(opts RateLimitOptions) func(http.Handler) http.Handler

RateLimit returns a rate-limit middleware. Call r.Use(RateLimit(opts)). RateLimit 返回限流中间件。 调用 r.Use(RateLimit(opts))。 Example / 示例:

r.Use(middleware.RateLimit(middleware.RateLimitOptions{Requests: 100, Window: time.Minute}))

func RateLimitKeyByIP

func RateLimitKeyByIP(ipv4PrefixBits, ipv6PrefixBits int, opts RateLimitKeyOptions) httprate.KeyFunc

RateLimitKeyByIP builds a rate-limit key from the client IP prefix. Forwarded headers are used only when TrustedProxies is set. RateLimitKeyByIP 根据客户端 IP 前缀构造限流键。 只有设置 TrustedProxies 时才会使用转发头。

func Recover added in v0.4.2

func Recover(opts RecoverOptions) func(http.Handler) http.Handler

Recover catches panics in the serving goroutine and logs the value and stack. After a response starts it aborts the request instead of writing another response. Hijacked connections are closed on panic. http.ErrAbortHandler is re-panicked without logging. Recover 捕获处理请求的 goroutine 中的 panic,记录其值和调用栈。 响应开始后会中止请求,不再写入第二个响应。 panic 时关闭已接管的连接;http.ErrAbortHandler 不记录日志,直接再次抛出。

func RequestID added in v0.4.2

func RequestID(next http.Handler) http.Handler

RequestID puts the incoming X-Request-Id, or a generated ID, in the context. It uses chi's request ID context, shared with AccessLog, and does not set a response header. RequestID 将传入的 X-Request-Id 或生成的 ID 放入 context。 使用与 AccessLog 共享的 chi 请求 ID context,不设置响应头。

func RequestIDFromContext added in v0.4.2

func RequestIDFromContext(ctx context.Context) string

RequestIDFromContext returns the request ID, or "" when absent or ctx is nil. RequestIDFromContext 返回请求 ID;不存在或 ctx 为 nil 时返回空字符串。

func RequireJSONBody added in v0.1.7

func RequireJSONBody(next http.Handler) http.Handler

RequireJSONBody requires Content-Type: application/json for requests with a body. Use routes.Use(RequireJSONBody) on routes that decode JSON. RequireJSONBody 要求带 body 的请求使用 Content-Type: application/json。 对会解码 JSON 的路由使用 routes.Use(RequireJSONBody)。 Example / 示例:

r.Post("/login", "Login", loginHandler, routes.Use(middleware.RequireJSONBody))

Types

type AccessLogOptions

type AccessLogOptions struct {
	Disabled bool
	Logger   *slog.Logger
	MinLevel slog.Level
	Skip     func(r *http.Request, status int) bool
	ClientIP clientip.Options
}

AccessLogOptions configures AccessLog. AccessLogOptions 配置 AccessLog。

type CORSOptions added in v0.4.2

type CORSOptions struct {
	// AllowedOrigins accepts exact origins or patterns with one '*'.
	// AllowedOrigins 接受精确来源或含一个 '*' 的模式。
	AllowedOrigins []string
	// AllowedMethods defaults to GET, HEAD, and POST. List methods explicitly.
	// AllowedMethods 默认允许 GET、HEAD 和 POST;请显式列出方法。
	AllowedMethods []string
	// AllowedHeaders defaults to Accept, Content-Type, and X-Requested-With; '*' allows all.
	// AllowedHeaders 默认允许 Accept、Content-Type 和 X-Requested-With;'*' 允许全部。
	AllowedHeaders []string
	ExposedHeaders []string
	// AllowCredentials permits credentials for the configured origins.
	// AllowCredentials 允许配置的来源携带凭证。
	AllowCredentials bool
	// MaxAge is the preflight cache duration, truncated to whole seconds.
	// Zero leaves the browser default unchanged.
	// MaxAge 是预检缓存时长,截断为整秒;零值保留浏览器默认值。
	MaxAge time.Duration
}

CORSOptions configures cross-origin access. No origins are allowed by default. CORSOptions 配置跨域访问;默认不允许任何来源。

type CompressOptions added in v0.4.2

type CompressOptions struct {
	// Level accepts -2, -1, or 1 through 9. Zero uses gzip.DefaultCompression.
	// Level 接受 -2、-1 或 1 到 9;零值使用 gzip.DefaultCompression。
	Level int
	// MinSize is the minimum response size in bytes. Zero uses 1024.
	// MinSize 是开始压缩的最小响应字节数;零值使用 1024。
	MinSize int
	// ContentTypes restricts compression to these media types when non-empty.
	// Empty uses gzhttp's content type filter. Wildcards are not supported.
	// ContentTypes 非空时仅压缩这些媒体类型;为空时使用 gzhttp 的类型过滤器。
	// 不支持通配符。
	ContentTypes []string
}

CompressOptions configures gzip response compression. CompressOptions 配置 gzip 响应压缩。

type RateLimitKeyOptions

type RateLimitKeyOptions struct {
	TrustedProxies []netip.Prefix
}

RateLimitKeyOptions configures RateLimitKeyByIP. RateLimitKeyOptions 配置 RateLimitKeyByIP。

type RateLimitOptions

type RateLimitOptions struct {
	Requests int
	Window   time.Duration
	KeyFunc  httprate.KeyFunc
	OnLimit  func(http.ResponseWriter, *http.Request)
}

RateLimitOptions configures RateLimit. RateLimitOptions 配置 RateLimit。

type RecoverOptions added in v0.4.2

type RecoverOptions struct {
	// Logger defaults to slog.Default at construction.
	// Logger 默认使用构造时的 slog.Default。
	Logger *slog.Logger
	// OnPanic writes the failure response before the response has started.
	// The pending Content-Length is cleared before the handler runs.
	// Nil uses http.Error with status 500 and no panic details.
	// OnPanic 在响应尚未开始时写入失败响应。
	// 调用前会清除待发送的 Content-Length。
	// nil 使用 http.Error 返回 500,不包含 panic 详情。
	OnPanic http.Handler
}

RecoverOptions configures panic logging and the failure response. RecoverOptions 配置 panic 日志和失败响应。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL