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

本地Angular调用Heroku部署的Node.js API出现CORS策略错误

问题根因排查与解决方案

1. 首先解决跨域配置的逻辑冲突

你当前的跨域头配置存在浏览器规范不允许的冲突:同时设置了Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true。根据W3C的跨域规范,带凭证(Cookie、Authorization头等)的跨域请求,不允许Access-Control-Allow-Origin使用通配符*,必须指定明确的允许域名。

2. 调整跨域中间件的配置和顺序

你已经安装了cors依赖,不建议手写跨域中间件,很容易漏处理预检请求,直接用官方依赖的配置更稳妥,且需要把跨域中间件放在所有路由定义的最前面:

const cors = require('cors');
app.use(cors({
  // 本地开发填你Angular应用的访问地址,比如http://localhost:4200,生产环境替换为线上前端域名
  // 需要支持多个域名可以传数组,或者传入函数做动态匹配
  origin: '你的前端应用实际域名',
  credentials: true,
  allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization'],
  methods: ['GET', 'POST', 'OPTIONS', 'PUT', 'HEAD', 'PATCH', 'DELETE']
}));

如果坚持要用手写的中间件,需要补充对OPTIONS预检请求的处理,否则Heroku的反向代理可能会拦截预检请求导致跨域头丢失:

app.use(function (req, res, next) {
  res.setHeader('Access-Control-Allow-Origin', '你的前端应用实际域名');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, HEAD,PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
  res.setHeader('Access-Control-Allow-Credentials', true);
  // 单独处理OPTIONS预检请求,直接返回204状态码
  if (req.method === 'OPTIONS') {
    return res.sendStatus(204);
  }
  next();
});

3. 优先修复接口的异步逻辑错误

你当前的接口代码存在严重的异步逻辑问题,这才是大概率的触发原因:

  • 回调嵌套形成闭包,循环变量的取值错乱,最终拿到的用户信息全是最后一次循环的内容
  • 异步数据库查询的完成顺序不确定,用j++计数的判断逻辑完全不可靠,很容易导致接口报错抛出500状态码

而Heroku默认的500错误页不会携带你自定义的跨域头,浏览器就会优先报CORS错误,掩盖了真实的接口错误问题。
建议用async/await重写接口逻辑,避免回调地狱:

app.get("/getNoOfUsersGuardians", async (request, response) => {
  try {
    const _userData = await database.collection("_User").find().toArray();
    const userArr = [];
    for (const user of _userData) {
      const userId = "_User$" + user._id;
      const guardianCount = await database.collection("GuardianInvitation").count({
        _p_fromUser: userId, 
        status:"accepted"
      });
      if (guardianCount <= 0) continue;
      const resultdevice = await database.collection("_Session").findOne({_p_user: userId});
      if (!resultdevice) continue;
      userArr.push({
        userid: userId,
        username: user.username,
        name: user.name,
        mobileno: user.phoneNumber,
        userEmail: user.email,
        phoneCountryCode: user.phoneCountryCode,
        _updated_at: user._updated_at,
        NoofGuardian: guardianCount,
        device: resultdevice.device
      });
    }
    if(userArr.length > 0){
      return response.send({ status: true, data: userArr, message: 'User list found that have Number of guardians' });
    }
    return response.send({ status: false, data: "", message: 'Guardians list not found' });
  } catch (error) {
    return response.status(500).json({ status: false, data: '', message: error.message });
  }
});

4. 最后排查Heroku运行日志

修改完成后如果还报错,直接查看Heroku的应用运行日志,确认接口请求是否有抛出异常、是否正常返回200状态码,优先解决业务代码的报错后再验证跨域问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:24:05