You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Heroku部署应用移动端出现跨域错误,请求技术解决方案

解决Heroku部署后移动端出现的CORS跨域错误

嘿,我明白你现在的困扰——桌面端访问正常,移动端却弹出CORS错误,这确实挺让人头疼的。结合你的技术栈(Express/Node后端 + AngularJS前端 + MongoDB),咱们一步步排查解决:

1. 先把Express的CORS中间件配置对

这是最核心的环节,很多时候都是配置不全导致的:

第一步:安装cors依赖(没装的话)

在后端项目根目录跑这个命令:

npm install cors --save

第二步:精准配置允许的Origin

打开你的Express主入口文件(比如app.js),替换或添加以下代码:

const cors = require('cors');
const express = require('express');
const app = express();

// 把你需要允许的域名都列在这里,包括Heroku的域名、本地开发地址,还有移动端可能用到的域名
const allowedOrigins = [
  'https://你的Heroku应用名.herokuapp.com',
  'http://localhost:4200', // 本地开发用
  // 如果移动端是PWA或者用了其他测试域名,记得加进来
];

app.use(cors({
  origin: function(origin, callback) {
    // 允许不带Origin的请求(有些移动端原生请求可能没有)
    if (!origin) return callback(null, true);
    // 检查当前请求的Origin是否在允许列表里
    if (allowedOrigins.indexOf(origin) === -1) {
      const errMsg = '当前域名不在CORS允许列表中';
      return callback(new Error(errMsg), false);
    }
    return callback(null, true);
  },
  credentials: true // 如果你的请求带Cookie、token这类认证信息,必须开这个
}));

// 别忘了挂载其他必要的中间件
app.use(express.json());
// ... 你的路由代码放在后面

这里要注意:如果你的前后端是部署在同一个Heroku应用里(比如前端打包后放在后端的public目录),那其实不需要跨域,但如果是分开部署的,必须确保后端允许前端的Origin。

2. 用Heroku环境变量动态管理允许的Origin

有时候移动端的请求可能来自不同的测试环境,硬编码Origin不够灵活,咱们用环境变量来配置:

第一步:在Heroku后台设置环境变量

登录Heroku,进入你的应用 → 「Settings」→ 「Config Vars」,添加一个名为ALLOWED_ORIGINS的变量,值用逗号分隔所有允许的域名,比如:https://你的前端域名.herokuapp.com,http://localhost:4200

第二步:在Express中读取这个环境变量

修改CORS配置代码:

// 从环境变量里读取允许的Origin,没有的话设为空数组
const allowedOrigins = process.env.ALLOWED_ORIGINS ? process.env.ALLOWED_ORIGINS.split(',') : [];

app.use(cors({
  origin: function(origin, callback) {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS policy'));
    }
  },
  credentials: true
}));

3. 检查AngularJS的请求配置

前端的请求设置也可能导致CORS失败,比如:

确保请求带对认证信息

如果后端开了credentials: true,AngularJS的请求必须加上withCredentials: true

$http({
  method: 'GET',
  url: 'https://你的后端域名.herokuapp.com/api/xxx',
  withCredentials: true
})
.then(function(res) {
  // 处理返回数据
})
.catch(function(err) {
  // 处理错误
});

如果用了自定义请求头

如果你在请求里加了Authorization这类自定义头,后端的CORS配置要明确允许这些头:

app.use(cors({
  origin: allowedOrigins,
  credentials: true,
  allowedHeaders: ['Content-Type', 'Authorization'] // 把你用的自定义头加进来
}));

4. 排查前后端部署方式

如果你的前后端是同一个Heroku应用,直接用Express托管前端静态文件就能避免跨域:

const path = require('path');
// 托管AngularJS打包后的静态文件
app.use(express.static(path.join(__dirname, 'public')));

// 所有非API请求都返回index.html(适配SPA路由)
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

这样前端请求后端API时用相对路径(比如/api/xxx),就不会有跨域问题了。

5. 打印移动端的请求Origin来排查

如果以上方法都没用,咱们直接看移动端到底是从哪个Origin发的请求:

在Express里加个中间件打印Origin:

app.use((req, res, next) => {
  console.log('当前请求的Origin:', req.headers.origin);
  next();
});

然后跑heroku logs --tail查看实时日志,找到移动端请求的Origin,把它加到allowedOrigins里就行。


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

火山引擎 最新活动