Preact项目CORS预检请求Header丢失及多预检问题求助
Preact项目与Loopback服务器CORS问题排查与解决
1. 预检请求丢失头部的原因
- 手动设置
Access-Control-Request-Headers干扰浏览器逻辑:这个头部是浏览器发送预检OPTIONS请求时自动生成的,用于告知服务器后续实际请求会携带的自定义头部。你手动在fetch配置中添加该头,会打乱浏览器的CORS处理流程,导致部分场景下无法正确传递api-target头。 - GET请求冗余的
Content-Type触发异常:GET请求默认无请求体,无需设置Content-Type: application/json。添加该头会让浏览器判定为“非简单请求”,但额外的自定义头配置会导致预检请求的头部生成逻辑混乱,出现头部丢失。 - 预检缓存机制冲突:若第一次预检响应未设置
Access-Control-Max-Age,或手动设置的头部导致缓存不匹配,浏览器第二次发送预检时无法复用缓存许可,进而丢失头部。
2. 解决CORS错误的方案
客户端调整
移除手动添加的Access-Control-Request-Headers,清理GET请求不必要的Content-Type:
const fetchOptions: RequestInit = { method: 'GET', headers: { 'api-target': 'rest', // 仅保留必要自定义头部 }, mode: 'cors', // 若需携带凭证(如Cookie),添加下方配置,服务端需对应调整origin // credentials: 'include', }; const fetchClubEventItems = async (): Promise<ClubEventItem[]> => { return fetch(`${BASE_URL}/public-guest-lists/${props.clubId}`, fetchOptions) .then((res) => { console.log('Response Headers:', res.headers); return res.json(); }); };
服务端修正
调整CORS配置的两个关键问题:
credentials: true时,origin不能设为*,必须指定具体前端域名;- 显式允许客户端发送的
api-target头部:
const corsOptions = { // 替换为你的前端实际域名,本地开发用http://localhost:8080 origin: 'http://localhost:8080', credentials: true, // 允许客户端传递的自定义头部 allowedHeaders: ['api-target'], // 设置预检缓存时长,减少重复预检请求 maxAge: 86400, // 缓存1天 }; expressApp.use(cors(corsOptions));
3. 出现两次预检请求的原因
- 预检缓存未生效:服务端未设置
Access-Control-Max-Age时,浏览器不会缓存预检许可,每次实际请求前都会重新发送预检;即使设置了该头,手动添加的头部导致缓存不匹配,也会触发第二次预检。 - 浏览器CORS处理逻辑差异:Chrome/Edge与Brave的CORS缓存策略、头部处理逻辑存在细微差异,Brave可能更严格保留自定义头部,而Chrome/Edge在第二次预检时因缓存冲突或逻辑异常丢失头部,导致两次预检。
- 手动设置
Access-Control-Request-Headers引发异常:该头的手动添加会让预检请求参数发生变化,无法复用第一次预检的缓存,从而触发第二次预检。
内容的提问来源于stack exchange,提问作者Adrian Royo
相关产品推荐
相关产品推荐

