Fiber 框架默认不自动解压 Gzip 请求体,需显式注册中间件(如 fiber.Compress 并启用 Request:true)或手写中间件实现解压;否则 c.Body() 返回压缩字节,导致解析失败或 panic。

Fiber 框架本身不自动解压 Gzip 请求体,必须显式注册中间件(如 fiber.Compress 或自定义 gzipRequest 中间件)才能处理 Content-Encoding: gzip 的请求体;否则 c.Body() 会读到乱码或空数据。
为什么默认不支持?
Fiber 是轻量级 HTTP 框架,设计上不内置请求体解压逻辑。它把 Content-Encoding 解析、流解压、body 缓存等全交给用户或中间件完成。这和 Spring Boot 的 server.compression.request.enabled=true 全局开关完全不同——Fiber 没有“服务器层自动解压”概念,只提供原始 http.Request.Body。
- 直接调用
c.Body()时,若请求头含Content-Encoding: gzip,返回的是压缩后的二进制字节,不是解压后 JSON - 不做任何处理就用
c.BodyParser(&v)解析结构体,大概率 panic:invalid character '\x1f' looking for beginning of value - 即使你手动
gzip.NewReader(c.Request().Body),也需注意Body只能读一次,后续中间件或路由逻辑会因Body已关闭而失败
用 fiber.Compress 中间件(推荐)
官方 fiber.Compress 默认只处理响应压缩,但可反向配置为「请求解压 + 响应压缩」双模式。关键点是启用 CompressConfig.Request 并指定 MimeTypes:
app.Use(fiber.Compress(fiber.CompressConfig{
Level: fiber.CompressBestSpeed,
Request: true, // ← 必须设为 true
MimeTypes: []string{"application/json", "application/xml", "text/*"},
Exceptions: []string{"/health", "/metrics"},
}))
- 该中间件会在请求进入时检查
Content-Encoding,自动解压并替换req.Body为解压后流 - 后续所有
c.Body()、c.BodyParser()、c.FormValue()都能正常工作 - 注意:它只对匹配
MimeTypes的请求生效,且要求Content-Type和Content-Encoding同时存在 - 如果客户端只发了
Content-Encoding: gzip却没带Content-Type,中间件会跳过,此时仍需自定义逻辑兜底
手写中间件解压(更可控)
当需要精细控制解压行为(比如只解压特定路径、记录解压失败日志、兼容 br 或 deflate)时,建议自己写中间件:
func gzipRequest() fiber.Handler {
return func(c *fiber.Ctx) error {
enc := c.Get("Content-Encoding")
if enc != "gzip" && enc != "x-gzip" {
return c.Next()
}
defer c.Request().Body.Close()
gr, err := gzip.NewReader(c.Request().Body)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid gzip body: "+err.Error())
}
defer gr.Close()
// 替换原始 Body,确保后续可多次读取(需缓存到内存)
body, _ := io.ReadAll(gr)
c.Request().ResetBody()
c.Request().SetBodyRaw(body)
return c.Next()
}
}
app.Use("/api/", gzipRequest())
- 必须调用
c.Request().ResetBody()+SetBodyRaw(),否则Body仍是压缩流 - 不能直接用
SetBodyStream(),因为gzip.Reader不支持重复读,且 Fiber 内部可能多次调用Body() - 大请求体(>几 MB)慎用
io.ReadAll(),容易 OOM;生产环境建议加maxSize限制并返回 413 - 如果还要支持
br,需引入github.com/andybalholm/brotli并分支判断enc
常见错误与绕过点
最容易被忽略的是:Fiber 的 BodyParser 默认不校验 Content-Type,但解压中间件依赖它。以下情况会导致解压失效:
- Postman 发送 gzip body 时忘了勾选「Encode request body」→ 实际没压缩,但 header 错误写了
Content-Encoding: gzip→ 中间件尝试解压失败 - 前端用
fetch手动设置headers: {'Content-Encoding': 'gzip'},但没真正压缩 body → 同上 - Spring Boot 客户端通过
feign.compression.request.enabled=true发请求,但服务端 Fiber 没配解压中间件 → 直接解析失败 - 使用
c.MultipartForm()处理文件上传时,即使 body 是 gzip,也不应解压——multipart 本身是二进制边界协议,gzip 套在上面无意义,反而破坏 boundary
真正要解压的,只有纯文本类请求体(JSON/XML/表单 URL 编码),且必须由客户端明确压缩、服务端明确识别并还原为原始字节流。这点比配置开关复杂得多,也更容易出 silent failure。


















