Nginx缓存层不处理非标准HTTP兼容,msie_padding和msie_refresh等指令需在响应生成阶段动态启用,并通过map提取老IE标识、纳入cache_key来避免缓存污染,推荐由后端统一适配。

Nginx 缓存层本身不负责兼容非标准 HTTP 请求,它只按标准 HTTP 协议缓存、校验和返回响应。所谓“兼容老旧浏览器的非标准行为”,比如 IE5.5–IE6 的响应截断或重定向失效,属于协议层适配问题,必须在响应生成阶段(即缓存前或缓存后注入阶段)处理,而非缓存机制本身能解决。
缓存与兼容性是两个独立环节
缓存层(proxy_cache)关注的是:响应是否可缓存、缓存多久、用什么 key 区分、是否过期、是否 stale 更新等。它不会修改响应体或响应头——除非你显式配置了 add_header 或 sub_filter 等指令。
而 msie_padding 和 msie_refresh 这类兼容指令,是在 Nginx 生成最终响应时起作用的,且仅对匹配特定 User-Agent 的请求动态生效。它们发生在:
- 后端响应已接收但尚未发送给客户端之前
- 且该响应未启用 chunked 编码、长度较短(如空响应)、Content-Length 准确可得
- 此时 padding 才会追加空格,refresh 才会补头
缓存中能否保留这些兼容头/填充?
可以,但需满足前提:
-
msie_refresh 添加的
Refresh头会被完整缓存,因为它是响应头的一部分 -
msie_padding 追加的空格属于响应体末尾内容,只要整个响应被缓存(即不是流式、未启用
proxy_buffering off),也会一并存入缓存 - 但注意:若缓存 key 未包含
$http_user_agent,则老 IE 和现代浏览器可能共用同一份缓存——导致现代用户也收到 Refresh 头或多余空格,这是错误的
安全启用兼容逻辑的关键配置
为避免缓存污染和误触发,应将兼容行为与缓存策略对齐:
- 在 server 或 location 块中,用 map 提取老 IE 标识:
map $http_user_agent $is_old_ie { ~MSIE\ [5-6]\. 1; default 0; } - 把
$is_old_ie加入 proxy_cache_key,确保老 IE 请求走独立缓存路径 - 仅对
$is_old_ie = 1的请求启用 msie_padding on 和 msie_refresh on - 禁用
chunked_transfer_encoding off—— 它与 msie_padding 冲突,且老 IE 本就不支持 chunked
更可持续的做法:让后端控制兼容性
比起在 Nginx 层做 UA 判断和响应修补,推荐由应用层统一处理:
- 对登录成功、AJAX 空响应等关键短响应,后端主动返回
Content-Length: 0或轻量 JSON,并视 UA 添加Refresh头 - Nginx 仅负责缓存这些已适配好的响应,不再承担协议修补职责
- 这样既避免 Nginx 配置耦合 UA 判断,也防止 CDN 或前置代理干扰 padding 计算


















