You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

本地CRA调用Next.js后端localhost接口遇CORS报错如何解决

问题背景
  • 现有已搭建完成的Create React App(CRA)前端项目,计划配套开发Next.js后端服务,暂不将整个应用迁移至Next.js技术栈
  • Next.js服务端已编写对应API路由,逻辑为调用第三方汇率接口、组装数据后返回响应,已通过Insomnia接口测试工具验证可正常返回结果
  • 服务运行端口:
    • Next.js后端:localhost:3000
    • CRA前端:localhost:3001
  • 异常现象: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请求代理到后端服务,绕过浏览器跨域限制:

  1. 在CRA项目的package.json中新增如下配置项:
"proxy": "http://localhost:3000"
  1. 修改前端请求代码,将绝对路径改为相对路径:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:48:18