Gzip压缩作用于响应体而非HTTP状态码,仅当响应满足Accept-Encoding头、非空body、匹配gzip_types且大小≥gzip_min_length时触发;Nginx需配置gzip_types包含text/html、application/json等以覆盖4xx/5xx错误页。

开启 gzip 压缩并不能压缩 HTTP 状态码本身——状态码(如 200、404、500)是响应行的一部分,不参与 gzip 压缩;gzip 作用于响应体(response body),即 Content-Length > 0 且存在实际内容的响应。但“全站状态码返回的带宽节省”实际指向的是:所有返回非空响应体的 HTTP 请求(无论 2xx、3xx、4xx、5xx),只要符合压缩条件,都应被动态压缩,从而减少整体传输体积。
关键不在“压缩状态码”,而在于确保各类响应体(包括错误页、API 错误 JSON、自定义 404/500 HTML 页面等)都被纳入 gzip 覆盖范围。
✅ 明确哪些响应体会被压缩
只有同时满足以下全部条件的响应,才会触发 gzip 压缩:
- 请求头含
Accept-Encoding: gzip(现代浏览器和主流客户端默认携带) - 响应状态码对应非空响应体(例如
200 OK返回 HTML、400 Bad Request返回 JSON 错误详情、500 Internal Server Error返回调试页面) - 响应头中
Content-Type属于服务器配置的gzip_types列表 - 响应体大小 ≥
gzip_min_length(避免压缩小内容反而增加开销) - 未被后端脚本手动禁用(如 PHP 中设了
header('Content-Encoding: identity')或zlib.output_compression = On冲突)
⚠️ 注意:纯状态响应(如
304 Not Modified、204 No Content)无响应体,不压缩;301/302若仅含Location头而无 body,也不压缩。真正可压缩的是你主动输出错误内容的场景,比如:
400 {"error":"invalid param"}404 <html><h1>Page not found</h1></html>500 {"message":"server error","trace":...}
✅ Nginx:覆盖全站各类响应体的 gzip 配置
在 http { } 块中统一启用,确保 PHP、Node.js、静态资源、错误页一并生效:
gzip on; gzip_min_length 256; # 小于256字节跳过(避免压缩开销反超收益) gzip_comp_level 5; # 平衡CPU与压缩率(不建议9) gzip_vary on; # 告知缓存层需按 Accept-Encoding 分别缓存 gzip_proxied any; # 即使经CDN或反向代理也启用压缩 gzip_types text/plain text/css text/javascript application/javascript application/json application/xml application/xhtml+xml application/rss+xml application/atom+xml application/x-httpd-php # PHP动态输出(含错误页) text/html; # 包括自定义4xx/5xx HTML模板
? 特别提醒:若使用 error_page 404 /404.html; 等自定义错误页,确保 /404.html 文件本身 MIME 类型为 text/html(Nginx 默认识别正确),且该文件内容长度 > gzip_min_length,即可被压缩。
✅ IIS:让 4xx/5xx 动态响应也进压缩流水线
IIS 默认只压缩 200 响应体,需显式放开其他状态码的动态压缩:
- 打开
applicationhost.config(路径:%windir%\System32\inetsrv\config\applicationhost.config) - 在
<httpCompression>节中确认启用动态压缩,并检查<dynamicTypes>是否包含:
<add mimeType="text/html" enabled="true" /> <add mimeType="application/json" enabled="true" /> <add mimeType="text/plain" enabled="true" />
- 关键一步:禁用
no-gzip响应头干扰
某些 ASP.NET 或 PHP 错误处理逻辑可能写入Cache-Control: no-cache, no-store或手动设置Vary: *,这会干扰压缩协商。确保错误响应中不出现:Content-Encoding: identity-
Vary: *(应为Vary: Accept-Encoding) -
Cache-Control: no-transform(会禁止代理压缩)
✅ PHP 场景避坑:不要让脚本抢跑压缩
若用 PHP 输出 JSON 错误(如 http_response_code(400); echo json_encode([...]);),务必关闭 zlib.output_compression:
- 检查
php.ini:zlib.output_compression = Off # 必须关!否则与 Nginx/IIS 压缩冲突,导致 double-compress 或乱码
- 不要手动加头:
// ❌ 错误:干扰协商 header('Content-Encoding: gzip'); // ✅ 正确:交给服务器统一处理 header('Content-Type: application/json; charset=utf-8'); http_response_code(400); echo json_encode(['error' => 'bad request']);
✅ 验证是否生效(针对各类状态码响应)
用 curl 测试任意返回 body 的非 200 响应:
curl -H "Accept-Encoding: gzip" -I -s https://yoursite.com/api/bad | grep "Content-Encoding"
# 应返回:Content-Encoding: gzip
curl -H "Accept-Encoding: gzip" -s -w "\nSize: %{size_download}\n" https://yoursite.com/404.html
# 对比未压缩请求(去掉 -H),确认体积明显下降浏览器开发者工具 → Network → 查看某条 400/500 请求的 Response Headers → 确认含 content-encoding: gzip 且 content-length 显著减小。
不复杂但容易忽略

















