ReactJS调用外部API出现CORS错误,求有效解决方案
首先纠正你一个关键错误:你在请求头里加的Access-Control-Allow-Origin、Access-Control-Allow-Methods这些是服务器返回给浏览器的响应头,前端请求里带这些完全没用,浏览器根本不会处理,反而可能让预请求(OPTIONS)变得更复杂,直接删掉这些头。
针对你的情况,分两种场景给解决方案:
临时开发环境(本地localhost调试)
方法1:正确使用浏览器CORS插件
如果你之前用插件没效果,大概率是没正确配置。比如用「Allow CORS: Access-Control-Allow-Origin」插件,要确保:
- 插件处于启用状态(图标亮着)
- 插件规则包含你的前端域名(http://localhost:3000)和目标API域名(https://rough-sun-2523.fly.dev)
- 刷新页面后重新测试
方法2:配置本地代理(推荐,稳定可靠)
以React项目为例,在项目根目录创建src/setupProxy.js文件,内容如下:
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { app.use( '/api', createProxyMiddleware({ target: 'https://rough-sun-2523.fly.dev', changeOrigin: true, }) ); };
然后修改你的请求代码,把目标地址改成相对路径:
const res: any = await fetch(`/api/${userPassport}/${dest}`);
重启项目后,浏览器会把/api开头的请求转发到目标API,这样就不会触发CORS了。
如果是Vite项目,在vite.config.js里配置proxy:
export default { server: { proxy: { '/api': { target: 'https://rough-sun-2523.fly.dev', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } }
方法3:验证API本身是否正常
先确认目标API能正常返回数据,执行命令:
curl https://rough-sun-2523.fly.dev/api/HK/US
如果能拿到正确的JSON,说明API没问题,问题确实出在CORS上。
正式环境部署
如果能控制目标API服务器
在服务器端配置CORS,比如Express框架下,安装cors中间件:
npm install cors
然后在代码里启用:
const cors = require('cors'); const express = require('express'); const app = express(); // 开发环境允许所有域名,正式环境建议指定具体域名 app.use(cors()); // 或者指定允许的域名 // app.use(cors({ // origin: 'https://your-production-domain.com', // methods: ['GET'] // })); // 你的API路由 app.get('/api/:passport/:dest', (req, res) => { // 处理逻辑 });
如果不能控制目标API
自己搭建一个简单的中转服务器,比如用Express写代理:
const express = require('express'); const cors = require('cors'); const axios = require('axios'); const app = express(); app.use(cors()); app.get('/api/:passport/:dest', async (req, res) => { try { const { passport, dest } = req.params; const response = await axios.get(`https://rough-sun-2523.fly.dev/api/${passport}/${dest}`); res.json(response.data); } catch (err) { res.status(err.response.status).json(err.response.data); } }); app.listen(3001, () => { console.log('Proxy server running on port 3001'); });
然后前端请求这个中转服务器的地址(http://localhost:3001/api/HK/US),部署后换成你的服务器域名。
最后说下为什么mode: 'no-cors'没用:这个模式下,浏览器会发起请求,但不会返回任何可读取的响应数据(返回opaque response),你没法调用res.json()拿到数据,完全不适合你的场景,直接放弃即可。
内容的提问来源于stack exchange,提问作者user16971617

