如何解决React应用调用newsapi.org时的CORS跨域问题?
React + Redux API调用遇到CORS跨域问题,仅客户端如何解决?
我正尝试在React应用中通过Redux的actions与reducers调用API,但浏览器出现了CORS跨域问题。由于我无法访问该API的内部配置,想了解是否可以仅通过客户端解决此问题,恳请各位提供帮助。
相关代码
newsActions.js
import * as types from './actionTypes'; const API_KEY = "<Redacted>"; export const getNewsApi = () => { debugger; return (dispatch, getState) => { dispatch({ type: 'API_REQUEST', options: { method: 'GET', service: 'news', mode: 'cors', headers:{ 'Access-Control-Allow-Origin':'*' }, endpoint: `https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=${API_KEY}`, actionTypes: { success: types.GET_NEWS_API_SUCCESS, error: types.GET_NEWS_API_ERROR } } }); } }
server.js
var express = require('express'); var app = express(); var cors = require('cors'); let __homeglobals = []; app.use(cors()); app.set("jsonp callback", true); var server = app.listen(8082, function () { var host = server.address().address; var port = server.address().port; console.log("Example app listening at http://%s:%s", host, port); });
若需更多信息或有疑问,请在下方留言。谢谢。
解决方案说明
首先得明确:纯前端代码是没办法绕过浏览器的CORS限制的——同源策略是浏览器的安全机制,除非目标API主动配置允许你的域名访问,否则直接从前端发起跨域请求肯定会被拦截。不过你已经有了自己的Node.js Express服务,可以把它改造成请求代理,完美解决这个问题。
步骤1:改造Express代理服务
在你的server.js里添加一个代理路由,让它帮你转发请求到NewsAPI,这样前端请求自己的服务就不存在跨域问题了:
var express = require('express'); var app = express(); var cors = require('cors'); var axios = require('axios'); // 先执行 npm install axios 安装依赖 let __homeglobals = []; app.use(cors()); app.set("jsonp callback", true); // 新增代理路由,处理新闻API请求 app.get('/api/news', async (req, res) => { try { const API_KEY = "<Redacted>"; // 把API Key移到服务端,避免前端暴露 const targetUrl = `https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=${API_KEY}`; const response = await axios.get(targetUrl); res.json(response.data); } catch (error) { res.status(error.response?.status || 500).json({ error: error.message }); } }); var server = app.listen(8082, function () { var host = server.address().address; var port = server.address().port; console.log("Example app listening at http://%s:%s", host, port); });
步骤2:修改Redux Action的请求地址
把原来直接请求NewsAPI的地址,改成请求你的代理服务地址:
import * as types from './actionTypes'; export const getNewsApi = () => { return (dispatch, getState) => { dispatch({ type: 'API_REQUEST', options: { method: 'GET', service: 'news', // 去掉多余的mode和无效的请求头,现在请求的是同源服务 endpoint: `http://localhost:8082/api/news`, actionTypes: { success: types.GET_NEWS_API_SUCCESS, error: types.GET_NEWS_API_ERROR } } }); } }
为什么之前的配置无效?
你在请求头里加Access-Control-Allow-Origin是搞错了对象——这个头是服务器返回给浏览器的响应头,不是前端发给服务器的请求头,前端设置它完全没用,浏览器会直接忽略。另外mode: 'cors'是浏览器跨域请求的默认模式,设置了也不会改变跨域拦截的结果。
其他可选方案(仅限调试或特殊场景)
- 浏览器插件临时禁用CORS:比如CORS Unblock这类插件,只能用于本地开发调试,绝对不能用于生产环境。
- JSONP方式:但NewsAPI不支持JSONP,所以这个方案对你不适用。
内容的提问来源于stack exchange,提问作者Eunicorn
相关产品推荐
相关产品推荐

