本地CRA调用Next.js后端localhost接口遇CORS报错如何解决
问题背景
- 现有已搭建完成的Create React App(CRA)前端项目,计划配套开发Next.js后端服务,暂不将整个应用迁移至Next.js技术栈
- Next.js服务端已编写对应API路由,逻辑为调用第三方汇率接口、组装数据后返回响应,已通过Insomnia接口测试工具验证可正常返回结果
- 服务运行端口:
- Next.js后端:
localhost:3000 - CRA前端:
localhost:3001
- Next.js后端:
- 异常现象:CRA项目中使用Fetch发起POST请求调用
http://localhost:3000/api/getExchangeRate接口时,浏览器控制台抛出CORS策略拦截错误:
Access to fetch at 'http://localhost:3000/api/getExchangeRate' from origin 'http://localhost:3001' has been blocked by CORS policy
原有实现代码
Next.js 侧API路由
import axios from 'axios'; export default async function(req, res) { const apiData = await axios.get( `https://api.exchangerate.host/latest?base=${req.body.from}&symbols=${req.body.to}&places=3` ); const dataKeys = Object.keys(apiData.data.rates); const newData = dataKeys.map((eachId) => { return apiData.data.rates[eachId]; }); const resRate = newData[0]; res.json({ rate: resRate, date: apiData.data.date }); }
CRA 侧请求逻辑
const testApi = () => { const body = { from: 'USA', to: 'ILS' }; console.log(JSON.stringify(body)); const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }; fetch('http://localhost:3000/api/getExchangeRate', requestOptions).then((response) => console.log(response)); };
可行解决方案
报错核心原因是浏览器同源策略限制:不同端口属于跨源请求,Next.js默认未配置跨域允许的响应头,请求会被浏览器拦截。以下两种方案可按需选择:
方案1:Next.js侧手动配置CORS响应头(零依赖,开发/生产环境均适用)
由于POST请求携带Content-Type: application/json头时,浏览器会先发送OPTIONS方法的预检请求,需要在API路由中配置对应允许规则,同时处理预检请求,修改后的Next.js代码如下:
import axios from 'axios'; export default async function(req, res) { // 配置跨域允许规则 res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3001'); res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); // 响应浏览器预检请求 if (req.method === 'OPTIONS') { return res.status(200).end(); } const apiData = await axios.get( `https://api.exchangerate.host/latest?base=${req.body.from}&symbols=${req.body.to}&places=3` ); const dataKeys = Object.keys(apiData.data.rates); const newData = dataKeys.map((eachId) => { return apiData.data.rates[eachId]; }); const resRate = newData[0]; res.json({ rate: resRate, date: apiData.data.date }); }
注意:Access-Control-Allow-Origin建议仅配置需要放行的前端源地址,不要直接设置为*,避免安全风险。如果后续有多个前端源需要放行,可以维护一个允许的源列表,根据请求Origin动态设置响应头。
方案2:CRA侧配置开发代理(无需修改后端,仅适用于本地开发场景)
CRA原生支持开发环境代理配置,可以把前端的API请求代理到后端服务,绕过浏览器跨域限制:
- 在CRA项目的
package.json中新增如下配置项:
"proxy": "http://localhost:3000"
- 修改前端请求代码,将绝对路径改为相对路径:
const testApi = () => { const body = { from: 'USD', // 注意:原代码写的USA不符合汇率接口要求,美元的货币代码为USD to: 'ILS' }; const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }; // 请求走本地代理,不会触发跨域 fetch('/api/getExchangeRate', requestOptions).then((response) => console.log(response)); };
注意:该配置仅在本地npm start启动开发服务时生效,生产环境部署仍需要后端配置正确的CORS规则,或通过Nginx等服务做反向代理实现同源访问。
内容的提问来源于stack exchange,提问作者Sapir
相关产品推荐
相关产品推荐

