必须用 proxy_ignore_headers cache-control 屏蔽后端缓存头,再以 proxy_cache_valid 显式设定有效期,才能让 nginx 主动控制缓存时长;需配合 proxy_cache my_cache 且缓存区已预定义,三者缺一不可。

直接用 proxy_ignore_headers Cache-Control 屏蔽后端返回的缓存指令,再用 proxy_cache_valid 显式设定你认可的有效期,就能让 Nginx 主动接管缓存时间决策——这不是绕过规则,而是把本该由你控制的逻辑,从不可靠的后端收回来。
为什么必须覆盖后端的 Cache-Control
后端常因框架默认(如 Django、Next.js、Spring Boot)或开发疏忽,对本该静态化的资源(JS/CSS/图片/API 配置)返回:
- Cache-Control: no-cache —— 强制每次回源验证,实际等效“禁用缓存”
- private 或 no-store —— 原意防敏感数据泄露,但若响应体不含用户信息,就是过度保护
- max-age=0 或 max-age=1 —— 技术上允许缓存,但周期短到失去意义
Nginx 默认严格遵循这些头,哪怕你知道该资源 1 小时内绝不会变,它也拒绝缓存。
核心三行配置(缺一不可,顺序不能错)
必须写在启用缓存的 location 块中,且放在 proxy_pass 之前:
-
proxy_ignore_headers Cache-Control;—— 大小写敏感,只影响 Nginx 缓存判断,不删除响应头 -
proxy_cache_valid 200 302 1h;—— 明确告诉 Nginx:对成功响应统一缓存 1 小时;可叠加proxy_cache_valid 404 1m;避免错误页长期卡住 -
proxy_cache my_cache;—— 必须已提前在http块中通过proxy_cache_path定义缓存区,否则整段配置无效
配套安全与兼容要点
忽略后端 Cache-Control 后,原本被标记为 private 或 no-store 的内容可能进入共享缓存,所以要确认:
- 检查响应体:确保不含手机号、token、session ID、用户昵称等动态或敏感字段
- 若后端还返回
Set-Cookie(如埋点 ID),需加proxy_ignore_headers Set-Cookie;和proxy_hide_header Set-Cookie; -
add_header Cache-Control不会覆盖上游头,如需强制生效,加always参数,例如:add_header Cache-Control "public, max-age=3600" always;
怎么验证是否生效
上线后立即打开浏览器 Network 面板检查:
- 响应头里仍可能看到后端原始的
Cache-Control: no-cache(这是正常的,proxy_ignore_headers不删头) - 但 Nginx 实际行为应按你写的
proxy_cache_valid执行:同一请求连续刷新,第二次起应返回200 HIT或X-Cache: HIT - 手动改一行 JS 再部署,清浏览器缓存重进——若仍是旧版,说明 location 优先级低、配置被其他块覆盖,或缓存区未正确启用











