nginx 默认不缓存 post 请求,因其语义非幂等、实现上$request_body不可靠、安全上需尊重后端禁用头;仅当满足只读+幂等+无用户上下文时,才可配合fastcgi_ignore_headers、签名key、fastcgi_cache_valid等配置安全启用。

默认只缓存 GET 和 HEAD 请求,这是 Nginx 的安全设计——POST、PUT、DELETE 等方法通常涉及状态变更或敏感操作,直接缓存容易引发重复提交、数据错乱或信息泄露。
为什么默认不缓存 POST
fastcgi_cache_methods 的默认值是 GET HEAD,Nginx 主动排除 POST 是出于三重考虑:
- 语义上,POST 本意是“创建或修改资源”,非幂等,缓存后可能把一次提交变成多次生效;
- 实现上,Nginx 默认不读取请求体($request_body),无法稳定构造区分不同参数的缓存 key;
- 安全上,后端常通过 Set-Cookie、Cache-Control: no-store 等头禁止缓存,Nginx 尊重这些响应头,即使配置了 POST 也会跳过。
哪些 POST 其实可以缓存
并非所有 POST 都不能缓存,关键看业务语义是否满足「只读 + 幂等 + 无用户上下文」:
- 前端搜索接口(如
/api/search)用 POST 提交 JSON 参数,但实际只查数据库、返回公开结果; - GraphQL 查询请求,method 是 POST,但 payload 固定、响应可预测且不含 session 或 cookie;
- 内部服务间调用的预热接口,参数由运维控制,无用户态数据。
启用 POST 缓存必须同步做的几件事
单加 fastcgi_cache_methods GET HEAD POST 没用,必须配套以下配置:
- 在 location 块中显式忽略干扰响应头:
fastcgi_ignore_headers Cache-Control Expires Set-Cookie; - 缓存 key 不能依赖 $request_body(Nginx 不保证其可用),推荐改用带签名的 query string 或后端注入的
X-Request-Sign头; - 明确设置缓存有效期:
fastcgi_cache_valid 200 5m,否则 POST 成功响应默认不进缓存; - 关闭 cache lock 或合理设超时:
fastcgi_cache_lock off,避免并发请求卡住缓存写入。
怎么验证是否真缓存了 POST
加一行响应头便于调试:add_header X-Cache $upstream_cache_status;。访问时观察响应头:
- 出现
X-Cache: HIT,说明命中缓存; - 若一直是
MISSED或BYPASS,重点检查 fastcgi_ignore_headers 是否漏配、cache_key 是否所有请求都一样、后端是否返回了 private/no-cache; - 登录页、下单接口等路径务必用
fastcgi_no_cache主动排除,避免误缓存。











