fiber不能直接使用标准库gzip.handler,因其基于fasthttp,ctx与net/http的responsewriter/request类型不兼容,强行包装会导致panic或静默失效;必须使用官方fiber.compression()中间件,它适配fasthttp生命周期,支持accept-encoding检查、状态码过滤、mime白名单及阈值控制。

Fiber 默认不压缩响应,必须显式启用压缩中间件;直接用 gzip.Handler 不行,因为 Fiber 不兼容标准库 http.Handler 接口。
为什么不能套用标准库 gzip.Handler
Fiber 基于 fasthttp,其 fiber.Ctx 和 fasthttp.RequestCtx 与标准库的 http.ResponseWriter / http.Request 不兼容。强行包一层 gzip.Handler(http.HandlerFunc(...)) 会 panic 或静默失效——根本收不到请求,更别说压缩了。
常见错误现象包括:服务启动无报错但所有响应头都没有 Content-Encoding: gzip,curl 测试返回 404 或空响应,或日志里反复出现 invalid request method。
正确做法:用 fiber.Compression() 中间件
Fiber 官方提供了开箱即用的压缩支持,封装在 fiber.Compression() 中,它已适配 fasthttp 生命周期,自动处理:Accept-Encoding 检查、状态码过滤(仅 2xx/3xx)、MIME 类型白名单、小响应跳过(默认阈值 1KB)、Vary: Accept-Encoding 头设置。
实操建议:
- 安装时无需额外依赖,
github.com/gofiber/fiber/v2v2.45+ 已内置 - 在
app.Use(...)中注册,位置应靠前(建议在Logger或Recover之后、路由注册之前) - 默认只压缩
text/html、application/json、text/css、text/javascript等类型;如需支持application/javascript或自定义类型,传入配置项fiber.CompressionConfig{Enable: true, Level: 6, MIME: []string{"text/html", "application/json", "application/javascript"}} - 压缩级别
Level可设为1(最快)到9(最高压缩),生产环境推荐6,避免设0(等效禁用)
哪些响应不会被压缩?容易踩的坑
即使启用了 fiber.Compression(),以下情况仍不会触发压缩:
- 响应状态码不是 2xx 或 3xx(比如
c.Status(400).JSON(...)被跳过) - 响应体原始字节长度 ≤ 1024(可调,通过
Threshold配置项修改) -
Content-Type不在白名单内(例如返回 JSON 却手动设了c.Set("Content-Type", "text/plain")) - 使用了
c.SendFile()或c.Attachment()且文件后缀未映射到可压缩 MIME(如.js默认是application/javascript,但.mjs可能被识别为application/octet-stream) - 中间件顺序错误:把压缩放在
app.Get(...)之后,导致该路由未经过压缩链
调试时用 curl -I -H "Accept-Encoding: gzip" http://localhost:3000/api/data 查响应头,重点看是否有 Content-Encoding: gzip 和 Vary: Accept-Encoding;若没有,先检查 Content-Type 输出是否符合预期。
流式响应(SSE、chunked)要绕过压缩
对长连接、Server-Sent Events 或分块传输的接口(如 c.Set("Content-Type", "text/event-stream")),fiber.Compression() 会自动跳过——这是安全行为,避免缓冲阻塞事件流。但如果你手动实现 streaming 并强制写入大量小块数据,仍可能因压缩器内部缓冲导致延迟升高。此时应显式禁用压缩:
app.Get("/stream", func(c *fiber.Ctx) error {<br> c.Set("Content-Type", "text/event-stream")<br> // 关键:跳过压缩中间件<br> c.Locals("fiber.compression.skip", true)<br> return c.SendString("data: hello\n\n")<br>})
fiber.Compression() 识别 c.Locals("fiber.compression.skip") == true 就会直接放行,不包装 writer。这个机制比自己写 wrapper 更轻量,也更可靠。











