Express+Node.js中POST请求CORS场景下缓存失效问题排查
以下是针对你遇到的POST请求缓存不生效问题的几个排查方向:
浏览器对POST缓存的默认规则限制
浏览器不会像GET请求那样默认缓存POST响应,必须满足明确的缓存条件:响应头要有合法的Cache-Control配置(比如private, max-age=3600),且不能存在no-store、no-cache这类禁用缓存的指令。另外要检查是否有Pragma: no-cache这类旧版头覆盖了缓存规则。
验证方式:在浏览器Network面板查看POST响应的Cache-Control头是否和你在控制器中设置的一致,有没有被其他头冲突覆盖。CORS凭证配置的影响
你开启了凭证(允许携带Cookie),当请求使用credentials: include时,Cache-Control不能设置为public——因为带凭证的响应只能存在私有缓存(浏览器本地),不能被共享缓存(比如CDN)存储。如果你的响应头设了public,浏览器会直接忽略缓存指令。
验证方式:把POST响应的Cache-Control改成private, max-age=3600,同时确认前端请求的credentials设置和服务器allowCredentials配置完全匹配。请求体的缓存键影响
POST请求的缓存键是URL + 请求体内容,哪怕请求体参数顺序、空格、编码有细微差别,浏览器都会判定为不同请求,不会复用缓存。比如两次POST的body是{"a":1,"b":2}和{"b":2,"a":1},就会被当成不同请求。
验证方式:在浏览器Network面板对比两次POST请求的Payload,确认内容完全一致;或者用固定的请求体重复发送,看是否触发缓存。服务器中间件的头覆盖问题
你使用的bodyParser、自定义CORS中间件可能在控制器设置Cache-Control之后,又修改了响应头。比如某些中间件会默认添加no-cache或must-revalidate这类指令,覆盖你的配置。
验证方式:在控制器设置完响应头后,立即打印console.log(res.get('Cache-Control')),再添加一个全局后置中间件,在响应发送前再次打印该头,对比两次输出是否一致。非简单请求的预检干扰
如果你的POST请求是非简单请求(比如Content-Type为application/json、带自定义请求头),浏览器会先发OPTIONS预检请求。如果预检请求的响应没有设置Access-Control-Max-Age来缓存预检结果,每次都会先发OPTIONS,但这不会直接导致POST响应不缓存——不过如果每次POST都能触发数据库查询,说明请求确实到达了服务器,核心还是POST本身的缓存规则没满足。
验证方式:检查请求的Content-Type,若为非简单请求,给OPTIONS响应添加Access-Control-Max-Age: 86400来缓存预检结果,再测试POST缓存。浏览器环境的特殊限制
隐私模式下浏览器会强制禁用缓存;部分浏览器对带Cookie的POST请求缓存有额外限制,即使配置了Cache-Control也可能不生效。
验证方式:切换到正常浏览器模式测试,若不需要携带Cookie,暂时去掉请求的credentials配置,看缓存是否生效;或者用curl命令模拟请求,查看服务器返回的响应头是否符合预期,排除浏览器本身的问题。
内容的提问来源于stack exchange,提问作者Bennyh961

