症状
控制台报 “Response to preflight request doesn’t pass access control check”;Network 面板只有 OPTIONS 请求,返回 404、405 或 500,真正的请求没有发出;curl 能成功而浏览器失败,说明是浏览器强制执行的 CORS 检查。
诊断
curl -i -X OPTIONS https://api.example.com/orders \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: content-type'
检查状态码与响应头:2xx 但缺少 Access-Control-Allow-Origin 仍会失败;404/405 表示 OPTIONS 没有被路由。再确认允许的来源与请求来源完全一致(协议、主机、端口),并检查浏览器 Network 面板中预检的详细信息。
根因
浏览器在发送某些跨源请求前先发送 OPTIONS,并要求响应明确允许来源、方法和请求头。缺少任一必需头或 OPTIONS 路由失败,浏览器就会在真正请求发出前阻止它。
修复
显式处理 OPTIONS,返回 204,并设置精确的 Access-Control-Allow-Origin、所需的 methods 与 headers、Vary: Origin;涉及 Cookie 时使用精确来源与 Access-Control-Allow-Credentials。
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: content-type
Vary: Origin
验证
重新执行预检,确认 204 与预期头;在浏览器中确认真实 POST 成功;再测试一个未授权来源,确认仍被阻止。不要为了消除错误而反射所有来源或允许 null。
常见陷阱
* 不能与凭据同时使用;代理可能剥离头;很多浏览器不允许预检发生重定向。应检查最终响应,而不只是第一跳。