Nginx 通过 map 指令可安全提取并标准化 Content-Encoding 请求头,实现按压缩类型分流处理;支持忽略大小写的正则匹配(如 gzip/br/deflate),未匹配则设为 identity,用于绕过缓存、拒绝请求、记录日志或透传至后端,并需设置 Vary 头保障缓存正确性。

当客户端发送带有 Content-Encoding: gzip 或 br 的请求时,Nginx 默认不会自动解压请求体(比如 POST 数据),也不会基于该头字段动态改变响应行为——但借助 map 指令,你可以安全、高效地实现「按编码类型分流处理」,例如:跳过缓存、启用特定日志标记、拒绝非标准压缩、或触发不同后端路由。
用 map 提取并标准化 Content-Encoding 值
map 块必须定义在 http 上下文中,它将原始请求头映射为自定义变量,支持正则匹配和默认值。关键点是:Nginx 不区分大小写解析头名,但 $http_content_encoding 变量值保留原始大小写,建议统一转小写处理:
http {
map $http_content_encoding $req_enc {
~*[Gg][Zz][Ii][Pp] gzip;
~*[Bb][Rr] br;
~*[Dd][Ee][Ff][Ll][Aa][Tt][Ee] deflate;
default identity;
}
}
说明:
- 正则使用
~*表示忽略大小写的匹配,覆盖常见拼写变体(如GZIP、gzip、Gzip) - 未匹配到任何压缩类型的请求(如无该头、或值为
identity、空字符串),统一设为identity - 该变量可在
server或location中直接引用,不参与实际解压,仅作逻辑判断依据
根据编码类型绕过缓存或拒绝请求
某些 API 明确禁止压缩请求体(如 Webhook 接口要求明文 JSON),或需对压缩请求启用更宽松的超时与缓冲区设置。此时可结合 proxy_cache_bypass 或 return 实现差异化控制:
location /api/submit {
# 若客户端发来 gzip/br 请求,直接拒绝
if ($req_enc !~ identity) {
return 400 "Compressed request bodies are not accepted";
}
<pre class='brush:php;toolbar:false;'>proxy_pass http://backend;}
location /assets/ {
对 gzip/br 请求跳过缓存(因压缩版本可能未预生成)
proxy_cache_bypass $req_enc; # 同时可添加响应头提示客户端:服务端未使用缓存 add_header X-Cache-Status "Bypassed (encoding: $req_enc)" always; proxy_pass http://static_backend;
}
注意:if 在 location 中慎用,仅适用于简单条件(如变量比对);避免在其中嵌套 proxy_pass。更健壮的方式是用 map 配合 proxy_cache_bypass 或 proxy_set_header。
记录编码类型用于调试与监控
在 access_log 中加入 $req_enc,能快速识别流量中压缩请求占比、排查客户端异常行为(如误发 br 但服务端不支持):
log_format encoding_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_user_agent" "$req_enc"';
<p>access_log /var/log/nginx/access-encoding.log encoding_log;</p>配合日志分析工具(如 awk、grafana + loki),可统计:
– 每分钟 br 请求数量
– gzip 请求的平均响应时间是否显著更高
– 是否存在大量 identity 请求却携带无效 Content-Encoding 头(表明客户端 bug)
进阶:联动后端路由与响应头重写
若后端服务需感知客户端压缩能力(例如返回预压缩的 HTML),可用 proxy_set_header 透传标准化后的编码类型,并在响应阶段根据 $req_enc 动态设置 Vary 头:
location /page/ {
proxy_set_header X-Client-Encoding $req_enc;
<pre class='brush:php;toolbar:false;'># 告知 CDN 或浏览器:响应内容随 Content-Encoding 变化
add_header Vary "Content-Encoding" always;
# 若客户端支持 br,且后端返回 br 响应,则额外加标识
proxy_intercept_errors on;
proxy_redirect off;
proxy_pass http://html_backend;
# 注意:add_header 不会覆盖已存在的 Vary,但需确保后端未重复设置}
提醒:Vary: Content-Encoding 是缓存正确性的关键。若你用 map 控制了响应路径,却忘了声明 Vary,CDN 或浏览器可能缓存错版本(如把 br 响应当作 gzip 返回给不支持 br 的客户端)。


















