应限制原始请求体大小而非日志字符串长度,须在读取body前用http.maxbytesreader拦截,避免破坏json、utf-8乱码及oom。

日志中间件里不能靠截断字符串来限大小
直接对日志消息做 string[:min(len(s), 1024)] 截断是错的——它会破坏 JSON 结构、切在 UTF-8 字节中间导致乱码,还绕过了真正的瓶颈:请求体读取和内存分配。真正要限制的是原始请求体大小,不是最终日志字符串长度。
必须在读 Body 前用 http.MaxBytesReader 拦截
Go 的 http.Request.Body 是流式接口,一旦开始读就无法 rewind。限大小的动作必须发生在任何读取操作之前,否则中间件或后续 handler 再调 io.ReadAll 或 json.NewDecoder 就可能 OOM。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
r.Body = http.MaxBytesReader(w, r.Body, 2 —— 限制单次请求体最多 2MB- 这个包装必须放在中间件最开头,甚至早于
c.Next()(gin)或next.ServeHTTP()(net/http) - 别传
nil当第一个参数:用w才能在超限时返回 413 状态码,而不是 panic 或静默丢数据
multipart 场景下还要额外设 ParseMultipartForm
仅靠 MaxBytesReader 不足以防住 multipart 攻击。Go 默认的 ParseMultipartForm 内存限额是 32MB,且它只在首次调用时生效;如果中间件提前消费了 Body,这个调用就会失败并报 http: request body too large。
- 必须在中间件里检查
r.MultipartForm == nil,然后立刻调r.ParseMultipartForm(10 (例如设 10MB) -
MaxMemory参数值要小于MaxBytesReader总限,留出 header 和 boundary 开销 - 若 handler 确实需要大文件上传,应单独路由、绕过该中间件,而非全局放宽限制
脱敏后日志内容本身不用再限长,但需防结构爆炸
日志消息体(比如 JSON 字符串)本身不构成内存风险,真正危险的是解析和重组过程。重点不是“这条日志打多长”,而是“会不会因为嵌套太深、字段太多导致 unmarshal 分配 GB 级内存”。
- 对 JSON 请求体做脱敏时,用
json.Unmarshal+ 递归遍历 map,但加深度限制(如 maxDepth=10),超深直接跳过解析、原样记为"{...}" - 敏感键匹配用预编译正则,避免每次新建
regexp.MustCompile;键名集合从配置加载,支持^.*token$这类模式 - query 参数脱敏后,记得同步更新
r.URL.RawQuery,否则日志里看到的还是原始未脱敏串
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










