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

使用fetch()调用含res.redirect()的接口时出现CORS错误及跳转问题

使用fetch()调用含res.redirect()的接口时遭遇CORS错误

当用fetch()调用后端带res.redirect()的接口时,一直触发CORS错误,但直接在浏览器地址栏访问该接口、或者用<a>标签跳转时,重定向完全正常。我知道这种逻辑是可行的,比如keycloak-connect这类npm包就实现了相同的重定向逻辑且运行正常,只是自己搞不定。

后端代码

const corsOptions = {
  origin: function (origin, callback) {
    callback(null, true);
  },
};

/** 返回前端HTML页面 **/
router.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "view", "index.html"));
});

/** 重定向接口 **/
// 尝试过修改/移除CORS配置,都没用
router.get("/redirector", cors(corsOptions), (req, res) => {
  res.redirect("https://google.com");
});

app.use(
  bodyParser.urlencoded({
    extended: true,
  }),
  bodyParser.json(),
  router
);

const server = http.createServer(app);
server.listen(8080, () => {
  console.log("http://localhost:8080");
});

前端代码

<body>
   <h1>Home</h1>
   <br />
   <button id="btn">调用重定向接口</button>

   <script>
      const btn = document.getElementById('btn');
      btn.addEventListener('click', async () => {
         try {
            const response = await fetch('/redirector');
         } catch (error) {
            console.error(error);
         }
      });
   </script>
</body>

运行效果演示

代码运行效果演示


问题原因

fetch()属于AJAX请求,浏览器会严格执行CORS策略。当后端返回3xx重定向时,fetch会自动跟进重定向到目标地址(这里是google.com),但google.com并没有配置允许你的前端域名的CORS规则,所以浏览器拦截了这个跨域请求,抛出CORS错误。而直接地址栏访问或<a>标签跳转属于浏览器顶级导航,不受AJAX的CORS限制。

解决方法

方法1:后端返回地址,前端主动跳转

不让fetch自动跟进重定向,后端返回目标URL,前端拿到后手动跳转:

  • 后端修改:
router.get("/redirector", cors(corsOptions), (req, res) => {
  res.json({ redirectUrl: "https://google.com" });
});
  • 前端修改:
btn.addEventListener('click', async () => {
  try {
    const response = await fetch('/redirector');
    const data = await response.json();
    window.location.href = data.redirectUrl;
  } catch (error) {
    console.error(error);
  }
});

方法2:用表单提交绕过AJAX限制

创建隐藏表单提交,和<a>标签跳转原理一致,属于浏览器顶级导航,不会触发CORS:

btn.addEventListener('click', () => {
  const form = document.createElement('form');
  form.method = 'GET';
  form.action = '/redirector';
  document.body.appendChild(form);
  form.submit();
  document.body.removeChild(form);
});

方法3:后端代理转发(仅适用于可控目标域名)

如果重定向目标是自己的服务,可以在后端做代理,避免前端跨域:

const axios = require('axios'); // 需先安装axios
router.get("/redirector", cors(corsOptions), async (req, res) => {
  try {
    const targetRes = await axios.get("https://google.com", { responseType: 'stream' });
    res.set(targetRes.headers);
    targetRes.data.pipe(res);
  } catch (err) {
    res.status(500).send(err.message);
  }
});

注意:此方法对google.com这类外部域名可能无效,对方可能有反爬或安全限制。


内容的提问来源于stack exchange,提问作者Kev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 11:43:19