Request ID 中间件
读取或生成请求 ID,贯穿日志、错误响应和审计链路
middleware/requestid 会为每个请求准备一个请求 ID。它先读取请求头里的 ID,如果没有或不合法,就生成新的 ID,并写入 ctx.RequestID() 和响应 Header。
请求 ID 是排查线上问题最基础的字段。一次请求经过网关、应用日志、审计日志、错误上报时,都应该带同一个 ID。
安装
go get github.com/duxweb/runa/middleware
基本用法
import "github.com/duxweb/runa/middleware/requestid"
route.Default().Use(requestid.New())
默认 Header 是 X-Request-ID
在 handler 中读取
route.Default().Get("/", func(ctx *route.Context) error {
return ctx.JSON(map[string]string{
"request_id": ctx.RequestID(),
})
})
自定义 Header 和生成器
route.Default().Use(requestid.New(requestid.Config{
Header: "X-Correlation-ID",
Generator: func() string {
return "req_" + time.Now().Format("20060102150405")
},
}))
生成器返回空字符串时,中间件会继续使用内置兜底生成器。
配置项
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
Next |
func(*route.Context) bool |
nil |
返回 true 时跳过 |
Header |
string |
X-Request-ID |
读取和写入的 Header 名称 |
Generator |
func() string |
内置随机生成器 | 没有有效请求 ID 时生成新 ID |
输入校验规则
外部传入的请求 ID 必须满足:
- 去掉首尾空白后不为空
- 长度不超过 128
- 只包含可打印 ASCII 字符
- 不包含控制字符
不满足时会被丢弃并重新生成
推荐顺序
把 request id 放在 logger、audit、auth 之前:
route.Default().Use(
recover.New(),
requestid.New(),
logger.New(),
)
这样后续日志和审计都能拿到 ctx.RequestID()
常见问题
- 已使用
security.New(...)时默认已经包含 request id - 如果上游网关已经生成请求 ID,保持同一个 Header 名即可
- 不建议把用户可控的长字符串直接作为请求 ID,中间件会自动做长度和字符校验