You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让CORS请求返回HTTP 304而非HTTP 200响应?

跨域请求无法触发304缓存响应问题排查与解决

问题现象

跨域RESTful请求中,尽管请求、响应头(包含If-None-Match和ETag)无变化,请求始终返回200 OK,从未触发304 Not Modified缓存响应。预检请求已通过Access-Control-Max-Age缓存,但所有实际XHR请求均返回200,且此问题仅在跨域场景下出现。

响应头信息

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://www.acme.com
Access-Control-Max-Age: 86400
Cache-Control: no-cache
Pragma: no-cache
Vary: Cookie, Origin

服务端代码片段

import express from 'express';
import cors from 'cors';

const server = express();
server
    .set( 'etag', 'strong' )
    .use( cors({
        credentials: true,
        maxAge: 86400,
        origin: 'http://www.acme.com'
    }) )
    .use(( req, res, next ) => {
        res.setHeader( 'Cache-Control', 'no-cache' );
        res.setHeader( 'Pragma', 'no-cache' );
        res.setHeader( 'Vary', `Cookie, ${ res.get( 'Vary' ) }` );
        next();
    })
    ...

问题根源

核心问题在于设置的Cache-Control: no-cache和Pragma: no-cache头。虽然no-cache理论上允许缓存验证,但在跨域带凭证(credentials: true)的场景下,浏览器与服务器的缓存交互逻辑会被这些头干扰,导致服务器无法正确触发304响应逻辑。同时,这类头会强制浏览器发起完整请求,弱化了ETag的缓存验证作用。

解决方案

1. 调整缓存控制头配置

移除强制不缓存的设置,替换为允许私有缓存且必须验证的配置,适配跨域带凭证的场景:

.use(( req, res, next ) => {
    // 允许私有缓存(仅当前用户可访问),且每次使用前必须向服务器验证
    res.setHeader( 'Cache-Control', 'must-revalidate, private' );
    // 移除Pragma头(仅兼容旧浏览器,现代浏览器无需)
    res.setHeader( 'Vary', `Cookie, ${ res.get( 'Vary' ) }` );
    next();
})

2. 确认ETag处理逻辑生效

你已通过server.set('etag', 'strong')开启强ETag验证,Express默认会自动处理If-None-Match请求头:当请求携带的If-None-Match与响应ETag一致时,自动返回304 Not Modified。需确保后续路由处理中未覆盖ETag或修改响应体内容(响应体细微变化会导致ETag改变,无法匹配)。

3. 确保跨域缓存兼容性

跨域带凭证的请求需满足:

  • 响应头包含Vary: Origin, Cookie(你的代码已配置,避免后续逻辑覆盖)
  • 缓存控制头不能包含no-store(禁止缓存资源的指令)

验证步骤

修改配置后重新测试:

  • 首次请求:服务器返回200 OK,携带ETag和调整后的Cache-Control头
  • 二次请求:浏览器自动携带If-None-Match头(值为首次请求的ETag)
  • 服务器对比ETag一致后返回304 Not Modified,浏览器使用本地缓存

内容的提问来源于stack exchange,提问作者Stephen Isienyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:09:13