fetch 报 cors 错误而非网络错误,是因为浏览器在跨域请求前先发 options 预检,若响应头缺失或不匹配 access-control-allow-origin,请求即被拦截,js 无法获取响应;curl 不受同源策略限制,故能通而前端不行。

为什么 fetch 会报 CORS error 而不是网络错误?
因为浏览器在发起跨域请求前,会先发一个 OPTIONS 预检请求(preflight),检查服务端是否允许该跨域操作。如果响应头里没带 Access-Control-Allow-Origin,或者不匹配当前源,fetch 就直接拒绝,根本不会把响应交给 JS —— 所以你看到的是 CORS 错误,而不是 404 或超时。
常见错觉是“后端接口能 curl 通,前端就该行”,但 curl 不受浏览器同源策略限制,它压根不发预检、也不校验响应头。
- 只有非简单请求(如带
Content-Type: application/json、自定义 header、PUT/DELETE方法)才触发预检 -
GET请求带Accept: application/json不触发预检;但加个Authorization: Bearer xxx就会 - 预检失败时,开发者工具 Network 面板能看到
OPTIONS请求返回 200,但后续POST请求被拦在浏览器层,甚至不出现在面板里
Access-Control-Allow-Origin: * 为什么有时不生效?
星号 * 确实允许任意源读取响应,但它和凭证(credentials)互斥:只要前端设置了 credentials: 'include'(比如要带 cookie 或 auth header),服务端就不能用 *,必须显式写成具体域名,例如 https://myapp.com。
否则浏览器会静默拒绝响应,控制台只报一句模糊的 Failed to fetch,连 CORS 相关提示都没有。
- 前端带凭证的写法:
fetch('/api/user', { credentials: 'include' }) - 对应后端响应头必须是:
Access-Control-Allow-Origin: https://myapp.com(不能是*) - 还要额外加:
Access-Control-Allow-Credentials: true,否则仍无效 - Chrome 对 localhost 和 127.0.0.1 视为不同源,开发时注意协议+端口+host 全匹配
Vue/React 项目里代理解决跨域,是绕过还是真跨域?
本地开发用 webpack devServer / vite / create-react-app 的 proxy 配置,本质是让开发服务器充当中间人:浏览器请求 /api/xxx,实际是发给本地 localhost:3000,它再转发到后端,全程同源。这不是“解决 CORS”,而是根本没触发跨域。
所以它只在 npm run dev 下有效,build 后部署到 Nginx 就失效 —— 那时浏览器直连后端,CORS 规则立刻生效。
- vite.config.ts 示例:
server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } - 这个
changeOrigin: true是改写请求头中的Host,避免后端因 Host 不匹配拒绝请求 - 代理不处理真实跨域场景(如 H5 页面嵌在第三方网站 iframe 里),那种必须靠后端配 CORS
fetch 发送 JSON 数据却卡在 pending,可能是预检没过
当用 fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(...) }) 时,浏览器判定这是非简单请求,会先发 OPTIONS。如果后端没处理 OPTIONS,或返回状态码不是 200,或者漏了 Access-Control-Allow-Headers(比如没声明允许 Content-Type),整个请求就会卡住,Network 面板显示 pending。
- 后端需响应
OPTIONS请求,并返回至少:Access-Control-Allow-Methods: POST, OPTIONS、Access-Control-Allow-Headers: Content-Type - Spring Boot 可用
@CrossOrigin注解,但注意它默认不包含OPTIONS处理,需额外配置 WebMvcConfigurer - Node.js + Express 建议用
cors中间件,而非手写 header,避免漏项
OPTIONS 上。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











