Documentation
¶
Overview ¶
Package middleware body.go 提供"从请求 Body 中提取 JSON 字段"的快捷方法。
为什么独立一个文件:
- 各框架的 Body 获取方式不同(*http.Request / *gin.Context / fiber.Ctx / *restful.Request)
- 对 Body 的读取必须满足"无副作用 + 防 OOM + 仅 JSON"三大要求
- 将共性逻辑抽到一个核心函数 sniffJSONField,各框架仅做适配
核心保障(与 README 示例保持一致):
- 只解析 Content-Type: application/json 的请求,其他(multipart/form/octet-stream 等)一律跳过
- 过滤无 body 的 HTTP 方法(GET/HEAD/DELETE/OPTIONS)
- 读取上限 MaxBodySniffSize(默认 10MB),超出即跳过,杜绝 OOM 风险
- 读取后必须"回填" body,保证业务 Handler 后续 BindJSON / ShouldBindJSON 正常工作
- 类型兼容:支持 "group_id":"g-1" 与 "group_id":123 两种写法
- 所有异常(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 ¶
- Variables
- func BodyJSONExtractorFromRequest(getReq func(trace.ExtractSource) *http.Request, path ...string) trace.FieldExtractor
- func Fiber(cfg *trace.TraceConfig) fiber.Handler
- func FiberBodyJSONExtractor(path ...string) trace.FieldExtractor
- func GRPCStreamServerInterceptor(cfg *trace.TraceConfig) grpc.StreamServerInterceptor
- func GRPCUnaryServerInterceptor(cfg *trace.TraceConfig) grpc.UnaryServerInterceptor
- func Gin(cfg *trace.TraceConfig) gin.HandlerFunc
- func GinBodyJSONExtractor(path ...string) trace.FieldExtractor
- func HTTP(cfg *trace.TraceConfig) func(http.Handler) http.Handler
- func HTTPBodyJSONExtractor(path ...string) trace.FieldExtractor
- func HTTPFunc(cfg *trace.TraceConfig, h http.HandlerFunc) http.HandlerFunc
- func Restful(cfg *trace.TraceConfig) restful.FilterFunction
- func RestfulBodyJSONExtractor(path ...string) trace.FieldExtractor
Constants ¶
This section is empty.
Variables ¶
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 ¶
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 ¶
func HTTPFunc(cfg *trace.TraceConfig, h http.HandlerFunc) http.HandlerFunc
HTTPFunc 便利函数:直接包装 http.HandlerFunc
func Restful ¶
func Restful(cfg *trace.TraceConfig) restful.FilterFunction
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.