Angular 5部署Heroku后调用HTTP接口遇混合内容阻塞问题求助
Hey there, let's work through this mixed content error you're hitting. First, let's break down why this is happening: modern browsers block HTTP requests from HTTPS pages as a security measure—they don't want unencrypted traffic potentially exposing sensitive data or opening you up to man-in-the-middle attacks. Since your third-party endpoint can't switch to HTTPS, we need a workaround using a proxy.
核心问题说明
你之前在
httpOptions里设置的Access-Control-Allow-Origin、Access-Control-Allow-Headers这些头是服务器响应头,前端请求时添加它们完全无效,这些应该由提供数据的服务器返回,所以先把这些无用的头删掉!
解决方案:在Heroku上搭建同域HTTPS代理
The only reliable way around this is to set up a proxy server that runs on your Heroku app (so it's HTTPS, same origin as your Angular app). This proxy will forward requests from your Angular app to the third-party HTTP endpoint, then send the response back to your frontend over HTTPS.
1. 创建Express代理服务器
在你的Angular项目根目录新建一个server.js文件,添加以下代码:
const express = require('express'); const request = require('request'); const path = require('path'); const app = express(); // 配置代理路由:把前端的/api/proxy请求转发到第三方HTTP接口 app.use('/api/proxy', (req, res) => { // 替换成你的第三方HTTP接口基础地址 const thirdPartyBaseUrl = 'http://your-third-party-endpoint.com'; // 拼接完整的请求URL(保留前端请求的查询参数和路径) const targetUrl = thirdPartyBaseUrl + req.originalUrl.replace('/api/proxy', ''); // 转发请求 req.pipe(request(targetUrl)).pipe(res); }); // 托管Angular编译后的静态文件 app.use(express.static(path.join(__dirname, 'dist/your-angular-app-name'))); // 处理SPA路由:所有非API请求都返回Angular的index.html app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'dist/your-angular-app-name/index.html')); }); // 启动服务器,监听Heroku分配的端口 const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Proxy server running on port ${PORT}`); });
2. 更新package.json配置
- 添加代理所需的依赖
- 修改启动脚本,让Heroku先编译Angular再启动代理服务器
{ "dependencies": { "express": "^4.18.2", "request": "^2.88.2" }, "scripts": { "start": "node server.js", "build": "ng build --prod", "heroku-postbuild": "npm run build" } }
3. 修改Angular的请求代码
把原来直接调用第三方HTTP接口的代码,改成调用我们的代理路由/api/proxy:
constructor(private http: HttpClient) { } // 只保留必要的请求头,删掉那些无效的CORS响应头 private httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }; // 现在通过代理获取数据 fetchThirdPartyData() { // 替换成你需要的具体请求路径,比如/api/proxy/users return this.http.get('/api/proxy/your-request-path', this.httpOptions); }
为什么这个方案有效?
- 你的Angular app(HTTPS)向同域的代理服务器(HTTPS)发起请求,浏览器不会触发混合内容限制
- 代理服务器作为后端服务,不受浏览器的混合内容规则限制,可以安全地向第三方HTTP接口发起请求
- 代理把第三方接口的响应转发回你的前端,全程在HTTPS环境下完成
内容的提问来源于stack exchange,提问作者Rich Blumer

