Iris 的 MaxRequestBodySize 配置常失效,因其仅在首次调用 c.Request().Body 前生效;一旦中间件或解析逻辑(如 ParseForm、Logger、ReadJSON)提前读取 body,原始 Body 即被消耗,限流失效;必须手动用 http.MaxBytesReader 在首个可能读 body 的逻辑前统一包装 r.Body。

为什么 Iris 的 MaxRequestBodySize 配置经常失效
Iris 没有自动拦截或重包装 r.Body 的机制,e.MaxRequestBodySize 仅在调用 c.Request().Body 前生效——一旦任何中间件、日志、解析逻辑(比如 c.ReadJSON()、c.FormValue()、c.PostValues())提前读取了 body,原始 r.Body 就被消费完毕,后续限流完全无效。
常见踩坑点包括:
- 自定义 JWT 或权限中间件里调了
r.ParseForm()或io.ReadAll(r.Body) - 启用了
iris.Logger且LogRequestBody: true,它会在中间件阶段就完整读取并缓存 body - 业务 handler 中绕过
c.ReadJSON(),直接用json.NewDecoder(c.Request().Body).Decode(),没手动套限流 - 使用了
c.MultipartReader()或c.FormFile()却没确认底层r.Body是否已被http.MaxBytesReader包装
必须手动用 http.MaxBytesReader 包装 r.Body
Iris 不提供开箱即用的全局 body 限流 wrapper,你得自己在中间件或 handler 开头显式包装。推荐统一放在中间件里,但要注意执行顺序:必须在任何可能读 body 的逻辑之前。
示例中间件写法:
func bodyLimitMiddleware(max int64) iris.Handler {
return func(ctx iris.Context) {
// ⚠️ 必须放在这里,且只执行一次
ctx.Request().Body = http.MaxBytesReader(ctx.ResponseWriter(), ctx.Request().Body, max)
ctx.Next()
}
}注册方式:
- 全局统一限流(如所有接口 ≤10MB):
app.Use(bodyLimitMiddleware(10 - 路由级差异化(如
/upload放宽到 50MB):app.Post("/upload", uploadHandler).Handle(bodyLimitMiddleware(50
multipart 场景下光限总大小远远不够
http.MaxBytesReader 确实能卡死总请求体,但在 multipart/form-data 中,攻击者可发一个 1KB 文本字段 + 9.99MB 文件,只要总大小不超限,就完全绕过防护——因为 r.ParseMultipartForm(maxMemory) 的 maxMemory 参数只控制内存缓存部分,超出自动落盘,不限制总上传量。
真正有效的组合是:
- 先用
r.Body = http.MaxBytesReader(..., 50<<20)限制总上传量(如 50MB) - 再调
r.ParseMultipartForm(8 << 20),设较小的maxMemory(如 8MB),让小文件走内存、大文件落磁盘 - 最后用
r.FormFile("file")获取磁盘句柄处理文件,而非r.FormValue()(后者依赖已解析的内存数据,且不适用于大文件)
别忘了清理临时文件和配合超时设置
即使加了 http.MaxBytesReader,如果 multipart 解析后不显式清理临时文件,磁盘空间仍会被占满;同时,若没有设置读取超时,慢速攻击者可分段发送超大 body,持续占用连接与缓冲资源。
关键补充项:
- 在 handler 结束后调用
r.MultipartReader().Close()或确保FormFile返回的*multipart.FileHeader被正确关闭 - 设置
app.ConfigureHost(func(su *iris.Supervisor) { su.Server.ReadTimeout = 15 * time.Second }) - 避免在中间件里调
ctx.ReadBody()或ctx.PostValues()—— 它们会提前消费 body,导致后续 handler 读不到数据
最易被忽略的一点:Iris 的 MaxRequestBodySize 是个“装饰器式”配置,它不改变底层行为,也不拦截连接;真要防住 OOM 和慢速攻击,http.MaxBytesReader + ReadTimeout + 临时文件清理,三者缺一不可。


















