在实际工程开发中,会有前后端分离的需求。
为了平滑的完成前端请求到后端各个独立服务,需要一个中间件实现请求转发的功能,利用Nginx可以实现,在这里,使用nodejs实现一个反向代理服务器。
实际前端项目背景是node+express做前端路由,提供页面的基础渲染和请求转发。
后端使用java springboot开发多个微服务(这里没有使用spring cloud Eureka 做服务管理与API协调),每个服务的IP一致,端口不一致。
实验环境:nodejs+express端口是3001,启动一个java服务,端口是8088,在java中添加了一个filter,用来输出收到的请求地址,使用postman左右客户端发起请求
@Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) req; System.out.println("请求地址是"+((HttpServletRequest) req).getRequestURI());
首先在原express工程下安装“http-proxy-middleware”中间件
npm install --save-dev http-proxy-middleware
在express的app.js中进行引用
var proxy = require(‘http-proxy-middleware‘);
根据实际使用情况,进行代理配置
1、转发所有http请求
var options = { target: ‘http://localhost:8088‘, // 目标主机 changeOrigin: true, // 需要虚拟主机站点 };var exampleProxy = proxy(options); //开启代理功能,并加载配置app.use(‘/‘, exampleProxy);//对地址为’/‘的请求全部转发
测试:向127.0.0.1:3001发起任何请求,查看java端接收的情况
请求URL | 服务接输入结果 |
127.0.0.1:3001/ | 请求地址是/ |
127.0.0.1:3001/test | 请求地址是/test |
127.0.0.1:3002/test | 不转发 |
2、转发指定path的请求
app.use(‘/api‘, exampleProxy);
测试:
请求URL | 服务接输入结果 |
127.0.0.1:3001/api/test | 请求地址是/api/test |
127.0.0.1:3001/test | 不转发 |
127.0.0.1:3001/api | 请求地址是/api |
127.0.0.1:3002/test | 不转发 |
3、对指定path规则进行重定向
var options = { target: ‘http://localhost:8088‘, // 目标主机 changeOrigin: true, // 需要虚拟主机站点 ws: true, // 是否代理websocket pathRewrite: { ‘^/api/old-path‘ : ‘/api/new-path‘, ‘^/api/remove/path‘ : ‘/path‘, ‘^/api/auth/login‘:‘/path‘ } };var exampleProxy = proxy(options); //开启代理功能,并加载配置app.use(‘/api‘, exampleProxy);//对地址为’/‘的请求全部转发
测试:
请求URL | 服务接输入结果 |
127.0.0.1:3001/api/old-path | 请求地址是/api/new-path |
127.0.0.1:3001/api/remove/path | 请求地址是/path |
127.0.0.1:3001/api/auth/login | 请求地址是/path |
127.0.0.1:3001/api/test | 请求地址是/api/test |
127.0.0.1:3001/test | 不转发 |
4、对指定规则进行路由重定向
这里可以简单理解为,加入目前我启动了2个及以上的java服务,端口分别是8088,8089,但前端发起的请求均是指向127.0.0.1:3001的,代理需要根据实际的前端请求,解析路径后,分发到不同端口(8088,8089)的java服务中
var options = { target: ‘http://localhost:8089‘, // 这里默认转发目标为127.0.0.1:8089 router: { ‘/rest‘: ‘http://localhost:8088‘,//如果请求路径是/api/rest,则将url的请求路由重定向 ‘127.0.0.1:3001/api/8003‘: ‘http://localhost:8003‘, // 服务该url则重定向 } };var exampleProxy = proxy(options); //开启代理功能,并加载配置app.use(‘/api‘, exampleProxy);//对地址为’/‘的请求全部转发
测试:
请求URL | 服务接输入结果 |
127.0.0.1:3001/api/rest | 8088:请求地址是/api/rest |
127.0.0.1:3002/api/rest | 无响应 |
127.0.0.1:3001/api | 8088:请求地址是/api |
127.0.0.1:3001/api/8003 | 转发失败(因为我们目前没有8003端口的服务) |
127.0.0.1:3001/api/rest/3232 | 8088:请求地址是/api/rest/3232 |
127.0.0.1:3001/api | 8089:请求地址是/api |
这里需要注意,代理默认对于/api下的所有请求,都转发至8089端口的服务,对于router中的配置采取例外处理,会工具规则转发至8088服务或8003服务
总结:
实际工程中,推荐采用第三种情况,通过“/api”等通配字符来区别所有要转发的请求和常规http的页面渲染请求。再根据实际后台服务接口,去配置不同的router规则即可。