Buffalo默认不限制大文件上传,需用中间件+http.MaxBytesReader在HTTP层拦截:检查Content-Length头并返回413,或包装Request.Body限制读取上限防内存溢出。

Buffalo 默认不拦截大文件上传
Buffalo 的 buffalo.Request 底层基于 Go 标准库的 http.Request,而标准库默认不限制 multipart/form-data 解析大小。这意味着用户可上传任意大小的文件,直到耗尽内存或触发系统超时,最终导致 panic 或 500 错误。
用 buffalo.MiddlewareFunc 在路由前拦截
最直接可控的方式是自定义中间件,在请求体解析前检查 Content-Length 头(适用于已知大小的普通表单上传)。注意:该头可被客户端伪造,仅作初步过滤,不能替代后端校验。
- 在
app.go的app.Use()调用前插入中间件 - 读取
c.Request().Header.Get("Content-Length"),转为int64 - 若超过阈值(如 10MB = 10_485_760),立即返回
c.Error(413, errors.New("request entity too large")) - 不要调用
c.Next(),避免后续解析
示例片段:
app.Use(func(c buffalo.Context) error {
if c.Request().Method == "POST" || c.Request().Method == "PUT" {
if cl := c.Request().Header.Get("Content-Length"); cl != "" {
if size, err := strconv.ParseInt(cl, 10, 64); err == nil && size > 10_485_760 {
return c.Error(413, errors.New("file too large"))
}
}
}
return c.Next()
})
用 http.MaxBytesReader 防止内存溢出
更安全的做法是在中间件中包装 Request.Body,强制限制读取上限。这能真正阻止大文件流入内存,且对所有方法(包括流式上传)生效。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
- 调用
http.MaxBytesReader(c.Response(), c.Request().Body, max) - 将结果重新赋给
c.Request().Body - 务必在
c.Next()前完成,否则后续 handler 仍可能读取原始 body - 错误会在实际读取时触发,需确保 handler 捕获
http.ErrBodyReadAfterClose或io.EOF类错误
关键点:此方式不依赖 Content-Length,防绕过更强,但无法提前返回 413,而是让后续 ParseMultipartForm 失败并抛出 http: request body too large。
为什么不用 ParseMultipartForm 参数控制?
Buffalo 并未暴露 Request.ParseMultipartForm 的 maxMemory 参数入口。即使你手动调用,也必须在中间件或 handler 开头执行,且仅限制内存缓冲区,不控制磁盘临时文件大小。更麻烦的是,Buffalo 内部可能已在某处隐式调用了该方法(比如通过 c.Param() 或 c.FormValue()),导致提前 panic。
所以硬编码 maxMemory 不可靠,容易和框架行为冲突;真正有效的限制必须落在 HTTP 层(中间件 + MaxBytesReader)或反向代理层(如 Nginx 的 client_max_body_size)。

















