RRuna

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,中间件会自动做长度和字符校验
编辑此页