默认仅缓存GET和HEAD请求,POST需显式配置fastcgi_cache_methods并同步处理请求体、响应头、cache_key及配套指令才能安全缓存。

默认只缓存 GET 和 HEAD 请求,这是最安全、最符合 HTTP 语义的做法。POST 等方法不参与缓存,不是 Nginx 的疏漏,而是有意为之的设计约束。
fastcgi_cache_methods 决定哪些请求能进缓存
该指令明确列出允许被 fastcgi_cache 缓存的 HTTP 方法。它不控制“是否缓存”,而是划定“缓存准入范围”:
- 未出现在列表中的方法(如 POST、PUT、DELETE),Nginx 直接跳过缓存逻辑,哪怕后端返回了
Cache-Control: public - 默认值是
GET HEAD,无需额外配置,适用于绝大多数 PHP 应用(WordPress、Laravel、Discuz 等) - 若需支持幂等的 POST(例如 JSON 搜索接口),必须显式加入:
fastcgi_cache_methods GET HEAD POST; - 该指令需放在已启用
fastcgi_cache的 location 块内,且不能被fastcgi_no_cache或fastcgi_cache_bypass覆盖
缓存 POST 不是加个方法就完事
仅修改 fastcgi_cache_methods 并不能让 POST 响应真正进入缓存。Nginx 还有两层隐性拦截:
-
请求体限制:Nginx 默认不缓存含请求体的响应(即大多数 POST),因为
$request_body不稳定、不可靠,且可能含敏感数据 -
响应头拦截:后端返回的
Cache-Control: no-cache、Set-Cookie或Expires会直接导致缓存跳过,即使方法已放开 - 必须同步配置
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;才能绕过这些限制 - 同时要禁用或谨慎配置
fastcgi_cache_lock,避免并发请求因锁机制误判而重复穿透
缓存键(cache_key)必须精准区分请求
POST 请求没有 URL 参数,若 key 构造不当,所有 POST 都会命中同一个缓存项,造成结果错乱:
- 禁止直接用
$request_body—— 它在多数场景下为空或不可读,且换行、空格、编码差异会导致 key 不一致 - 推荐方案:前端将查询参数转为 query string,改用 GET;或后端解析 POST body 后生成唯一签名(如 SHA256),通过
X-Request-Signheader 返回,再写入 key:fastcgi_cache_key "$scheme$request_method$host$request_uri$upstream_http_x_request_sign"; - key 中避免包含用户态变量(如
$cookie_sessionid、$remote_addr),否则无法共享缓存,失去意义
配套指令缺一不可
启用 POST 缓存是一组协同动作,单点配置无效:
-
fastcgi_cache_valid 200 302 5m;—— 明确声明成功响应的缓存有效期,否则即使缓存成功也立即过期 -
fastcgi_cache_bypass $arg_nocache $cookie_nocache;—— 提供调试入口,比如加?nocache=1可临时绕过缓存 -
add_header X-Cache $upstream_cache_status;—— 在响应头中输出缓存状态(HIT/MISS/EXPIRED),用于验证是否生效 - 对登录、下单、用户中心等路径,建议用
map主动排除:map $request_uri $no_cache { ~^/(login|order|account) 1; },再配合fastcgi_no_cache $no_cache;


















