如何用Angular 5访问仅允许内网访问的NodeJS服务器?
嘿,这个需求我之前刚好碰到过,给你分开发环境和生产环境两种场景来梳理解决方案,都能实现所有HTTP请求走同一端口的目标:
一、开发环境:用Angular CLI代理转发
Angular CLI自带了代理功能,刚好能解决开发时的跨域和端口统一问题,步骤很简单:
在项目根目录新建
proxy.conf.json文件,配置转发规则:{ "/api/*": { "target": "http://你的内网NodeJS服务地址:端口", "secure": false, "changeOrigin": true, "logLevel": "debug" } }这里的
/api/*是你Angular请求里的前缀,所有以这个开头的请求都会被转发到内网的NodeJS服务。修改启动配置,让Angular CLI加载这个代理文件:
- 打开
angular.json,找到projects -> 你的项目名 -> architect -> serve -> options,添加一行:"proxyConfig": "proxy.conf.json" - 或者直接修改
package.json里的scripts,把start命令改成:"start": "ng serve --proxy-config proxy.conf.json"
- 打开
在Angular代码里发起请求时,直接用
/api/xxx的格式,比如:this.http.get('/api/user/list').subscribe(res => { // 处理响应 });这样所有请求都会通过Angular CLI的端口(默认4200)转发到内网服务,完全满足同一端口的要求。
二、生产环境:两种可行方案
生产环境下需要考虑部署架构,这里给你两个常用的方案:
方案1:用NodeJS门面层同时托管Angular静态文件和转发请求
把Angular编译后的静态文件放到你的NodeJS门面层项目里,让这个NodeJS服务既提供静态文件访问,又负责转发API请求到内网后端:
先编译Angular项目:
ng build --prod编译完成后会生成
dist文件夹。在NodeJS门面层项目里,用Express托管静态文件,并配置API转发:
const express = require('express'); const httpProxy = require('http-proxy'); const app = express(); const proxy = httpProxy.createProxyServer({}); // 托管Angular静态文件 app.use(express.static('path/to/your/angular/dist/folder')); // 转发API请求到内网NodeJS后端 app.all('/api/*', (req, res) => { proxy.web(req, res, { target: 'http://内网NodeJS服务地址:端口', changeOrigin: true }); }); // 监听端口(比如3000) app.listen(3000, () => { console.log('服务启动在端口3000'); });这样用户访问
http://你的门面层地址:3000时,既可以加载Angular页面,所有/api开头的请求也会通过这个端口转发到内网后端,完全实现同一端口。
方案2:用Nginx反向代理
如果你的团队更倾向于用Nginx做静态资源托管和反向代理,这也是个靠谱的选择:
把Angular编译后的
dist文件夹放到Nginx的静态资源目录(比如/usr/share/nginx/html)。修改Nginx的配置文件(通常是
/etc/nginx/nginx.conf或者站点配置文件),添加反向代理规则:server { listen 80; server_name 你的域名或IP; # 托管Angular静态文件 root /usr/share/nginx/html; index index.html; # 处理Angular的路由刷新问题 location / { try_files $uri $uri/ /index.html; } # 转发API请求到内网NodeJS后端 location /api/ { proxy_pass http://内网NodeJS服务地址:端口; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }重启Nginx后,用户访问Nginx的端口(默认80),静态资源和API请求都走这个端口,Nginx负责把API请求转发到内网服务。
内容的提问来源于stack exchange,提问作者João Paulo

