nginx 默认不主动缓存非幂等请求但可能因上游响应头或宽松配置意外缓存,必须显式绕过;应使用 map + proxy_cache_bypass 拦截 post/put/delete,配对 proxy_no_cache 禁写缓存,并对敏感路径如 /api/v1/ 双重兜底。

Nginx 默认不缓存 POST、PUT、DELETE 等非幂等请求的响应,但这只是“不主动缓存”,并非“自动绕过”。如果上游服务错误返回了 Cache-Control: public,或路径匹配了宽松的缓存 location,这些请求仍可能意外进入缓存——导致重复提交、状态错乱甚至数据泄露。所以必须显式配置绕过逻辑,不能依赖默认行为。
用 map + proxy_cache_bypass 主动拦截
这是最清晰、可维护性最强的方式:把危险方法映射为非空值,再让该值触发缓存跳过。
- 在
http块中定义映射:
map $request_method $no_cache {
POST "1";
PUT "1";
DELETE "1";
default "";
}
- 在对应
location中启用绕过:
proxy_cache_bypass $no_cache;
只要变量值非空(如 "1"),Nginx 就不会查缓存,直接回源。
配合 proxy_no_cache 彻底禁用缓存写入
proxy_cache_bypass 控制“是否读缓存”,而 proxy_no_cache 控制“是否写缓存”。两者建议配对使用,杜绝漏网之鱼:
proxy_no_cache $no_cache;
这样即使某次响应被错误判定为可缓存(例如后端误设 Cache-Control: public, max-age=3600),也不会真正存入缓存区。
对敏感路径做双重保险
除了按方法控制,还应结合路径语义强化策略。比如所有以 /api/v1/ 开头的接口,默认视为不可缓存:
location ^~ /api/v1/ {
set $no_cache "1";
proxy_cache_bypass $no_cache;
proxy_no_cache $no_cache;
}
这种写法优先级高于 map,适合快速兜底关键业务路径。
验证是否生效
加一个响应头方便调试:
add_header X-Cache-Status "$upstream_cache_status";
发起 POST 请求时,响应头中应看到 X-Cache-Status: MISS 或 BYPASS,而非 HIT。同时检查日志里 $upstream_cache_status 字段是否始终未出现 HIT。











