nginx 可解压上游 gzip 响应(gunzip on)或压缩下游响应(gzip on + gzip_proxied),需区分二者、避免双重压缩;须配合 proxy_buffering on、proxy_hide_header content-encoding,并通过 accept-encoding 头和响应体大小等验证生效。

当后端已返回 gzip 压缩的响应,而客户端(如老旧浏览器或某些嵌入式设备)不支持解压时,Nginx 可以在反向代理链路中先解压再转发;反之,若后端未压缩、但客户端支持压缩,Nginx 可统一接管压缩。关键在于区分“解压上游响应”和“压缩下游响应”两件事,不能混用同一组指令。
让 Nginx 解压后端已压缩的响应(gunzip on)
启用 gunzip on 后,Nginx 会在收到带 Content-Encoding: gzip 的上游响应时自动解压,再按需处理(如重写头、缓存、再压缩等)。它只作用于 proxy_pass 流量,且仅支持 gzip,不支持 Brotli(br)。
- 必须配合
proxy_buffering on(默认开启),否则流式转发无法解压 - 建议加
proxy_hide_header Content-Encoding,避免解压后仍透传旧头导致客户端误判 - 不推荐与
gzip on同时对同一响应做“解压后再压”,除非明确需要重压缩(如改变压缩级别或修复损坏包)
让 Nginx 压缩后端未压缩的响应(gzip_proxied + gzip on)
这是更常见的优化场景:后端(如 Spring Boot、Node.js)关闭自身压缩,由 Nginx 统一压缩响应体。此时必须用 gzip_proxied 显式授权压缩权限,否则即使 gzip on 开启,Nginx 默认也不压代理响应。
-
gzip_proxied any:最简方案,对所有代理响应尝试压缩(含 200/404/500 等状态码) - 生产推荐:
gzip_proxied expired no-cache no-store private auth,按响应头语义精准触发,兼顾安全与效率 - 务必加
gzip_vary on,确保 CDN 或浏览器缓存能识别Vary: Accept-Encoding - 检查后端是否误传
Content-Encoding—— 若有,Nginx 默认跳过压缩,需先用proxy_hide_header屏蔽
避免双重压缩或解压失败
典型冲突场景包括后端和 Nginx 都开启 gzip,导致响应被压两次(体积可能更大甚至乱码),或 Nginx 尝试解压非 gzip 内容。需统一压缩责任边界:
- 后端应用层关闭所有响应压缩(如 Tomcat 的
compression="on"、Express 的compression()中间件) - Nginx 配置中禁用后端透传的压缩头:
proxy_hide_header Content-Encoding和proxy_hide_header Vary(若不依赖 Vary 缓存) - 用
curl -H "Accept-Encoding: gzip" -I https://yoursite.com/path实测:看返回头是否有Content-Encoding: gzip和Vary: Accept-Encoding,响应体是否真实变小
验证与调试要点
实际生效与否,不能只看配置语法正确,要结合请求头、响应头和真实内容判断:
- 客户端必须发送
Accept-Encoding: gzip,否则 Nginx 不会启动压缩流程 - 响应体长度需 ≥
gzip_min_length(默认 20 字节),小 JSON 错误响应容易被跳过 - 若响应含
Cache-Control: no-transform,部分中间设备(如企业网关)可能阻止压缩,Nginx 默认尊重该头 - 日志中可添加
$gzip_ratio变量记录压缩率,便于定位低效资源











