Fiber默认不压缩响应,因压缩是可选中间件而非核心功能,开启会增加CPU开销且对小响应可能增大体积;开发者需显式注册gzip.New()并确保路径匹配、顺序正确、客户端支持gzip协商。

为什么 Fiber 默认不压缩响应?
因为压缩是可选的中间件,不是核心功能。开启后会增加 CPU 开销,且对小响应(如 JSON API 返回几十字节)反而可能变大。Fiber 把决定权留给开发者,避免隐式行为影响性能预期。
常见错误现象:Content-Encoding: gzip 没出现,但客户端(如 curl 或浏览器)明明发了 Accept-Encoding: gzip;或者手动加了 gzip.New() 却没生效——大概率是中间件注册顺序不对,或没匹配到路径。
用 gzip.New() 中间件开启压缩
这是最常用方式,基于 github.com/gofiber/fiber/v2/middleware/compress。注意包路径里有 v2,v1 和 v2 的导入路径不同,混用会报错。
- 必须在
app.Use()中注册,且放在路由定义之前(否则中间件不触发) - 默认只压缩
text/*、application/json、application/javascript等 MIME 类型,不压缩图片或二进制流 - 压缩级别默认是
gzip.DefaultCompression(6),可设为gzip.BestSpeed(1)或gzip.BestCompression(9),但高阶别对小响应收益极低
import "github.com/gofiber/fiber/v2/middleware/compress"
app := fiber.New()
app.Use(compress.New()) // 启用默认配置
app.Get("/api/data", func(c *fiber.Ctx) error {
return c.JSON(map[string]string{"msg": "hello world"})
})
自定义压缩条件和 MIME 类型
有些场景需要压缩 application/octet-stream(比如导出 CSV 文件),或跳过某些路径(如健康检查接口 /health)。这时得传入配置对象。
立即学习“go语言免费学习笔记(深入)”;
-
Level:控制压缩强度,compress.LevelBestSpeed或数值 1–9 -
Threshold:响应体字节数低于该值时不压缩,默认 1024;设为 0 表示全部尝试压缩(不推荐) -
Next:函数类型,返回true表示跳过压缩,例如:func(c *fiber.Ctx) bool { return c.Path() == "/health" } -
MIME:追加支持的 MIME 类型,如[]string{"text/csv", "application/vnd.ms-excel"}
app.Use(compress.New(compress.Config{
Level: compress.LevelBestSpeed,
Threshold: 512,
Next: func(c *fiber.Ctx) bool {
return c.Path() == "/health" || c.Get("X-No-Compress") == "1"
},
MIME: []string{"text/csv"},
}))
验证压缩是否生效及常见陷阱
最容易被忽略的是:客户端没发 Accept-Encoding: gzip,服务端就不会压缩。不要只看服务端代码,要抓包或用 curl -H "Accept-Encoding: gzip" -I http://localhost:3000/api/data 测试响应头。
- 响应头必须含
Content-Encoding: gzip,且Content-Length明显变小 - 如果用了反向代理(Nginx / Cloudflare),它们可能提前解压并重写响应头,导致你看到的不是 Fiber 发出的原始响应
- Fiber 的
c.SendString()和c.JSON()支持压缩,但c.Status(200).Send([]byte{...})若手动设置了Content-Length,可能干扰中间件判断 - 压缩中间件对流式响应(
c.Context().SetBodyStreamWriter)无效,需自行处理
复杂点在于:压缩不是“开个开关就完事”,它依赖客户端协商、MIME 判定、内容长度阈值、中间件执行时机,还有代理层的二次干预。漏掉任意一环,都会让你以为“配置没起作用”。


















