React中POST请求为什么被CORS拦截?预检请求没发出去?
在React项目里用fetch发POST请求到第三方API时,浏览器突然报CORS错误。我明明设置了headers里的Content-Type为application/json,但控制台显示”Response to preflight request doesn’t pass access control check”。
试过在headers加mode: ‘cors’和credentials: ‘omit’,但问题依旧。奇怪的是同样的代码在本地测试环境没问题,部署到生产环境就拦截了。难道预检请求没发出去?代码如下:
const sendRequest = async () => {
try {
const response = await fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({ name: 'test' })
});
return response.json();
} catch (error) {
console.error('CORS error:', error);
}
};
检查Network面板发现只有POST请求被拦截,没有看到OPTIONS预检请求。生产服务器是Nginx配置的,是不是需要特别开启预检支持?
从你的描述来看,生产环境用的是Nginx,很可能是Nginx没有正确处理OPTIONS请求,或者响应头里缺少必要的CORS字段。你可以按照以下步骤排查和解决:
先检查一下Nginx的配置文件,确保它能正确处理OPTIONS请求。可以在server块里加上类似下面的配置:
这段配置的意思是,当收到OPTIONS请求时,直接返回204状态码,并添加必要的CORS响应头。
然后,再检查一下Nginx对其他请求的CORS支持,确保每个正常的请求也带上这些响应头。比如:
另外,如果你的服务端用了反向代理,确保代理层不会把OPTIONS请求过滤掉或者改写。有时候代理层会默认丢弃非GET/POST请求,这就导致预检请求根本到不了后端。
最后,补充一点,你在fetch里加的
mode: 'cors'其实是多余的,因为fetch默认就是cors模式。而credentials: 'omit'可能会导致某些需要认证的接口出问题,建议去掉试试。改完Nginx配置后记得重启服务:
sudo nginx -s reload,然后清空浏览器缓存再试一次。如果还是有问题,可以用curl命令手动模拟一个OPTIONS请求,看看返回的响应头是不是符合预期。比如这样:总之,重点是让Nginx正确处理OPTIONS请求并返回合适的CORS头。搞定这个,问题应该就解决了。