直接用proxy_ignore_headers屏蔽后端禁止缓存头,使Nginx自主决策缓存行为;必须忽略Cache-Control、Expires、Set-Cookie、Vary等头,并配合proxy_cache_valid、add_header和proxy_hide_header确保安全生效。

直接用 proxy_ignore_headers 屏蔽后端返回的不合理缓存头,再由 Nginx 按你设定的规则决定是否缓存、缓存多久——这不是“修复后端”,而是把缓存决策权收回到代理层。
哪些头属于“不合理”且必须忽略
后端常因框架默认、开发疏忽或历史兼容原因,对本该长期缓存的静态资源返回禁止缓存指令。这些头正是 proxy_ignore_headers 要处理的对象:
- Cache-Control: no-cache / no-store / private / max-age=0:Nginx 默认完全遵守,导致 JS/CSS/图片等构建产物无法缓存
- Expires: 过期时间早于当前(如 1970-01-01):Nginx 视为不可缓存,跳过写入逻辑
- Set-Cookie:即使只是埋点 ID 或匿名跟踪 Cookie,Nginx 也会拒绝缓存整条响应
- Vary: User-Agent:让同一 URL 生成移动端/桌面端两份缓存,浪费空间且降低命中率
典型配置写法(以哈希化静态资源为例)
假设后端对 /_next/static/ 或 /*.js?hash=abc 响应统一加了 Cache-Control: no-cache,但你知道这些是构建产物、内容不变、可安全缓存 1 年:
在对应 location 块中写:
location ^~ /_next/static/ {
proxy_pass http://nextjs_backend;
proxy_ignore_headers Cache-Control Expires Set-Cookie Vary;
proxy_cache_valid 200 302 1y;
proxy_cache my_cache;
add_header Cache-Control "public, immutable, max-age=31536000" always;
add_header X-Cache-Status $upstream_cache_status;
}
注意:proxy_ignore_headers 必须写在 proxy_pass 之后、proxy_cache 相关指令之前;多个头用空格分隔,不能换行或加标点。
配套动作不能少
仅忽略头还不够,必须同步做三件事,否则容易出问题:
-
主动注入安全缓存头:用
add_header Cache-Control "public, immutable, max-age=..." always,确保下游(浏览器或 CDN)收到明确、友好的缓存指令 -
隐藏原始干扰头:加
proxy_hide_header Cache-Control;和proxy_hide_header Set-Cookie;,防止客户端看到被忽略却仍透传的错误头 - 确认内容无状态:检查响应体是否含用户敏感字段(如 token、手机号、session ID)。若含,即使头被忽略,也不应缓存
怎么验证真生效了
别只看配置,要观察实际行为:
- 用
curl -I请求两次相同资源,首次响应头含X-Cache-Status: MISS,第二次含HIT→ 缓存已启用 - 响应头中不再出现
Cache-Control: no-cache或Set-Cookie→proxy_hide_header生效 - 响应头中存在
Cache-Control: public, immutable, max-age=31536000→ 主动注入成功 - 查看缓存目录(如
/var/cache/nginx/...)下是否有对应文件且更新时间与首次请求一致 → 磁盘缓存写入正常


















