CORS错误本质是浏览器拦截响应而非请求失败:请求已抵达后端并返回200,但因缺失Access-Control-Allow-Origin等头,浏览器拒绝将响应暴露给JS;预检失败时主请求甚至不发出。

因为浏览器在 CORS 检查失败时,根本不会把响应内容(包括响应头)暴露给 JavaScript —— 这是同源策略的强制保护机制,不是“没显示”,而是“不允许你看到”。
错误发生时,响应其实已经存在
当你看到 “No 'Access-Control-Allow-Origin' header is present” 这类报错,通常意味着:请求已成功到达服务端、服务端也返回了 HTTP 200 响应、但响应中缺少必需的 CORS 头。浏览器收到这个响应后,直接拦截,不交给 fetch 或 XMLHttpRequest 的回调函数处理,所以你拿不到 response.headers、response.statusText,甚至 response.status 都可能是 0。
Network 面板里能看到响应头,但 JS 拿不到
浏览器开发者工具的 Network 标签页运行在浏览器 UI 层,权限高于网页脚本,因此你能点开请求、查看完整的 Request Headers 和 Response Headers;但 JavaScript 运行在沙箱环境里,受同源策略约束,只有通过 CORS 授权的响应,才被允许读取其状态和头部信息。
- 如果服务端返回了 Access-Control-Allow-Origin: https://your-app.com,且 Origin 匹配,JS 就能正常读取 response.headers.get('Content-Type')
- 如果服务端漏了这个头,或值为 * 但前端带 credentials,JS 就完全无法访问 response 的任何属性(除了 type === 'opaque' 这种不可读状态)
预检失败时,主请求甚至不会发出
当请求触发 OPTIONS 预检(比如用了 Authorization 头、application/json 类型、或 DELETE 方法),而服务端对 OPTIONS 返回了 404、500,或压根没返回 CORS 头,浏览器会直接终止流程,连真正的 GET/POST 请求都不会发。此时 Network 面板里只看到一个失败的 OPTIONS 请求,主请求根本不会出现 —— 所以你更不可能在 JS 里拿到它的响应头。
怎么确认服务端到底返回了什么
唯一可靠的方式是:打开 Network 面板 → 找到对应请求(注意区分 OPTIONS 和主请求)→ 点开 → 切到 Headers 标签页 → 查看 Response Headers 部分。重点核对:
- Access-Control-Allow-Origin 是否存在、值是否匹配当前页面 origin
- Access-Control-Allow-Credentials 是否为 true(如需 Cookie)且 Allow-Origin 不是 *
- Access-Control-Allow-Headers 是否包含你发送的自定义头(如 Authorization)
- OPTIONS 请求是否返回 200 + 完整 CORS 头,且没有被中间件拦截


















