为什么浏览器发了 OPTIONS 请求却没发真正的 POST 请求?
我在用 React 调后端接口时,发现控制台里只看到一个 OPTIONS 请求,但我的 POST 请求根本没发出去,这是为啥?后端同事说跨域配置没问题,但我本地开发时就是请求失败。
我试过加 headers,也试过换不同的 Content-Type,但都没用。下面是我发起请求的代码:
fetch('https://api.example.com/upload', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'test' })
})
.then(res => res.json())
.then(data => console.log(data));
但关键点来了——如果后端没正确响应预检请求,真正的 POST 就根本不会发出去,浏览器直接就拦住了。
你代码本身没问题,问题大概率出在后端没正确处理 OPTIONS 请求,或者响应头没配对。
你后端同事说“跨域配置没问题”,那八成是只加了
Access-Control-Allow-Origin,但没处理预检的其他必填头。正确处理预检请求,后端需要对 OPTIONS 请求返回这些响应头:
-
Access-Control-Allow-Origin: https://your-frontend-domain(或者*,但不推荐生产用)-
Access-Control-Allow-Methods: POST, GET, OPTIONS(必须包含 OPTIONS)-
Access-Control-Allow-Headers: Content-Type, Authorization(你用了Content-Type,所以这里必须显式声明)-
Access-Control-Max-Age: 86400(可选,缓存预检结果,减少重复请求)另外,Content-Type 为 application/json 的 POST 请求本身就属于“非简单请求”,一定会触发预检,这点你得记牢。
本地开发建议用代理绕开跨域,比如在
package.json里配:然后前端请求改成
fetch('/upload', {...}),这样就走本地 dev server 代理了,浏览器不会触发 OPTIONS,开发体验能舒服很多。如果一定要直连后端,那就让后端把 OPTIONS 请求的响应头检查清楚,注意响应状态码要是 200 或 204,千万别返回 404 或 500,不然浏览器直接认定“这接口不支持跨域”,你的 POST 就石沉大海了。
你先让后端查查 OPTIONS 请求的响应头和状态码,基本都能定位到问题。