middleware

package
v1.3.12 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package middleware body.go 提供"从请求 Body 中提取 JSON 字段"的快捷方法。

为什么独立一个文件:

  • 各框架的 Body 获取方式不同(*http.Request / *gin.Context / fiber.Ctx / *restful.Request)
  • 对 Body 的读取必须满足"无副作用 + 防 OOM + 仅 JSON"三大要求
  • 将共性逻辑抽到一个核心函数 sniffJSONField,各框架仅做适配

核心保障(与 README 示例保持一致):

  1. 只解析 Content-Type: application/json 的请求,其他(multipart/form/octet-stream 等)一律跳过
  2. 过滤无 body 的 HTTP 方法(GET/HEAD/DELETE/OPTIONS)
  3. 读取上限 MaxBodySniffSize(默认 10MB),超出即跳过,杜绝 OOM 风险
  4. 读取后必须"回填" body,保证业务 Handler 后续 BindJSON / ShouldBindJSON 正常工作
  5. 类型兼容:支持 "group_id":"g-1" 与 "group_id":123 两种写法
  6. 所有异常(IO 错误、畸形 JSON、字段缺失、null 值)全部静默降级为"未命中"

Package middleware grpc.go 提供 gRPC 服务端的 Unary 和 Stream 拦截器。

gRPC 特殊性:

  • 使用 metadata.MD 替代 HTTP Header
  • metadata key 在 gRPC 内部强制转为小写
  • 响应头通过 grpc.SetHeader 写入

Package middleware 提供各主流框架的链路追踪中间件。

所有中间件共享统一的处理流程(见 trace.Process), 各框架中间件仅负责"适配输入/输出"——将框架特定的请求对象转换为 trace.ExtractSource。

使用 Go 的编译时依赖裁剪:用户只引入自己使用的中间件符号,未使用的框架依赖不会进入最终二进制。

Index

Constants

This section is empty.

Variables

View Source
var MaxBodySniffSize int64 = 10 << 20 // 10MB

MaxBodySniffSize Body 读取上限,防止恶意大包 / 文件上传 / 媒体流导致 OOM。 默认 10MB;业务可在 init 中全局覆盖:

func init() { middleware.MaxBodySniffSize = 2 << 20 } // 改为 2MB

Functions

func BodyJSONExtractorFromRequest

func BodyJSONExtractorFromRequest(getReq func(trace.ExtractSource) *http.Request, path ...string) trace.FieldExtractor

BodyJSONExtractorFromRequest 从 *http.Request 安全读取并提取 JSON 字段 适用于:net/http、Gin、go-restful(它们的底层都是 *http.Request)

path 支持多级嵌套:["data", "group_id"]

func Fiber

func Fiber(cfg *trace.TraceConfig) fiber.Handler

Fiber 返回 Fiber v3 框架的追踪中间件

使用示例:

app := fiber.New()
app.Use(middleware.Fiber(trace.DefaultConfig()))
app.Get("/hello", func(c fiber.Ctx) error {
    // 以下写法均可正确输出追踪字段:
    logger.Ctx(c).Info("hi")
    logger.Ctx(c.Context()).Info("hi")
    // 也可通过 Fiber 原生 API 读取:
    rid, _ := c.Locals("request_id").(string)
    return c.SendString("ok")
})

若 cfg 为 nil,使用 trace.DefaultConfig()

func FiberBodyJSONExtractor

func FiberBodyJSONExtractor(path ...string) trace.FieldExtractor

FiberBodyJSONExtractor 返回一个 FieldExtractor:从 Fiber 请求的 JSON body 中提取字段。

Fiber 的 body 由框架内部缓存(fasthttp 特性),读取后无需回填。

特性:

  • 仅解析 Content-Type: application/json
  • 超过 MaxBodySniffSize(默认 10MB)跳过
  • 任何异常静默降级为"未命中"

path 支持多级嵌套:FiberBodyJSONExtractor("data", "group_id")

使用示例:

cfg := trace.NewConfig().WithRequestID().
    AddField(&trace.TraceField{
        Name:      "group_id",
        Extractor: middleware.FiberBodyJSONExtractor("group_id"),
    })
app.Use(middleware.Fiber(cfg))

func GRPCStreamServerInterceptor

func GRPCStreamServerInterceptor(cfg *trace.TraceConfig) grpc.StreamServerInterceptor

GRPCStreamServerInterceptor 返回 gRPC Stream 服务端拦截器

使用示例:

srv := grpc.NewServer(grpc.StreamInterceptor(
    middleware.GRPCStreamServerInterceptor(trace.DefaultConfig()),
))

func GRPCUnaryServerInterceptor

func GRPCUnaryServerInterceptor(cfg *trace.TraceConfig) grpc.UnaryServerInterceptor

GRPCUnaryServerInterceptor 返回 gRPC Unary 服务端拦截器

使用示例:

srv := grpc.NewServer(grpc.UnaryInterceptor(
    middleware.GRPCUnaryServerInterceptor(trace.DefaultConfig()),
))

若 cfg 为 nil,使用 trace.DefaultConfig()

func Gin

func Gin(cfg *trace.TraceConfig) gin.HandlerFunc

Gin 返回 Gin 框架的追踪中间件

使用示例:

r := gin.New()
r.Use(middleware.Gin(trace.DefaultConfig()))
r.GET("/hello", func(c *gin.Context) {
    // 以下四种写法等价,均可正确输出追踪字段:
    logger.Ctx(c).Info("hi")
    logger.Ctx(c.Request.Context()).Info("hi")
    // 也可通过 Gin 原生 API 读取:
    rid := c.GetString("request_id")
    rid, _ := c.Get("request_id")
})

若 cfg 为 nil,使用 trace.DefaultConfig()

func GinBodyJSONExtractor

func GinBodyJSONExtractor(path ...string) trace.FieldExtractor

GinBodyJSONExtractor 返回一个 FieldExtractor:从 Gin 请求的 JSON body 中提取字段。

特性(与 middleware.readAndRestoreJSONBody 一致):

  • 仅解析 Content-Type: application/json
  • 超过 MaxBodySniffSize(默认 10MB)跳过
  • 读取后自动回填 body,不影响后续 c.ShouldBindJSON
  • 任何异常静默降级为"未命中"

path 支持多级嵌套:GinBodyJSONExtractor("data", "group_id")

使用示例:

cfg := trace.NewConfig().WithRequestID().
    AddField(&trace.TraceField{
        Name:      "group_id",
        Extractor: middleware.GinBodyJSONExtractor("group_id"),
    })
r.Use(middleware.Gin(cfg))

func HTTP

func HTTP(cfg *trace.TraceConfig) func(http.Handler) http.Handler

HTTP 返回标准 net/http 中间件,自动注入追踪字段到 r.Context(),并回写响应头

使用示例:

handler := middleware.HTTP(trace.DefaultConfig())(myHandler)
http.ListenAndServe(":8080", handler)

若 cfg 为 nil,使用 trace.DefaultConfig()(仅 request_id 字段)

func HTTPBodyJSONExtractor

func HTTPBodyJSONExtractor(path ...string) trace.FieldExtractor

HTTPBodyJSONExtractor 返回一个 FieldExtractor:从 net/http 请求的 JSON body 中提取字段。

特性:

  • 仅解析 Content-Type: application/json
  • 超过 MaxBodySniffSize(默认 10MB)跳过
  • 读取后自动回填 body,不影响后续 Handler 的解码
  • 任何异常静默降级为"未命中"

path 支持多级嵌套:HTTPBodyJSONExtractor("data", "group_id")

使用示例:

cfg := trace.NewConfig().WithRequestID().
    AddField(&trace.TraceField{
        Name:      "group_id",
        Extractor: middleware.HTTPBodyJSONExtractor("group_id"),
    })
http.ListenAndServe(":8080", middleware.HTTP(cfg)(myHandler))

func HTTPFunc

HTTPFunc 便利函数:直接包装 http.HandlerFunc

func Restful

Restful 返回 go-restful v3 框架的追踪过滤器(FilterFunction)

使用示例:

ws := new(restful.WebService)
ws.Filter(middleware.Restful(trace.DefaultConfig()))

ws.Route(ws.GET("/hello").To(func(req *restful.Request, resp *restful.Response) {
    // 业务层获取追踪字段:
    logger.Ctx(req.Request.Context()).Info("hi")
    // 也可通过 go-restful 原生 API 读取:
    rid, _ := req.Attribute("request_id").(string)
}))

或注册到 container:

container := restful.NewContainer()
container.Filter(middleware.Restful(trace.DefaultConfig()))

若 cfg 为 nil,使用 trace.DefaultConfig()

func RestfulBodyJSONExtractor

func RestfulBodyJSONExtractor(path ...string) trace.FieldExtractor

RestfulBodyJSONExtractor 返回一个 FieldExtractor:从 go-restful 请求的 JSON body 中提取字段。

特性:

  • 仅解析 Content-Type: application/json
  • 超过 MaxBodySniffSize(默认 10MB)跳过
  • 读取后自动回填 body,不影响后续 req.ReadEntity
  • 任何异常静默降级为"未命中"

path 支持多级嵌套:RestfulBodyJSONExtractor("data", "group_id")

使用示例:

cfg := trace.NewConfig().WithRequestID().
    AddField(&trace.TraceField{
        Name:      "group_id",
        Extractor: middleware.RestfulBodyJSONExtractor("group_id"),
    })
container.Filter(middleware.Restful(cfg))

Types

This section is empty.

Jump to

Keyboard shortcuts

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