使用node反向代理接口改造旧项目

1,374 阅读4分钟

前情说明

最近公司分配了一个旧系统维护任务,该系统用的是 springBoot,前后端没有分离,前端使用的是 jQuery+easyUI,并且和后端代码在一个总目录下,前端代码托管在后端起的静态服务下,由于前端对 SpringBoot 不熟,之前做修改都是前端代码改完之后用 maven 编译一下来查看,修改完之后又得重启下服务,并且还只能用本地服务调试。这也太影响效率了,虽然也不是不能开发,但是对于习惯了webpack的热更新的我来说,这简直就像回到了解放前,鉴于开发任务也不是很紧,对项目一番分析,发现前后端完全可以分离,转发一下请求服务的地址就行,跟一直做得 vue.config.js 里的 proxyTable 是一个意思。

本来准备用 NGINX 来配置的,然鹅我对 NGINX 也是只了解皮毛,网上的教程看的也一知半解,只好用 Node 来实现了,至少我司的前端还能看懂。说干就干,一番搜索下来,使用express起一个简单的静态服务,然后使用http-proxy-middleware代理下接口请求就可以了.

匹配规则的设置

http-proxy-middleware文档还是比较清晰的,看着文档也能配置出来一些,主要是接口匹配规则上,之前接口代理一般做的都是类似 将以/api开头的请求转发到测试服务器,然而这次碰到的是需要将以.do结尾的请求转发到目标服务器上,以.do结尾的规则是*.do,但是前面的路径咋配置呢,在这里走了一些弯路,由于不清楚前面路径的配置,我使用了pathRewrite方法,在里面对 path 进行判断来进行转发,虽然也可行,但是后面增加了需要代理的规则就得修改判断条件,比较麻烦。经过一段时间的摸索,发现其实两个星号就是代表着任意,**/*.do就代表着以.do结尾的请求,这样匹配规则就完成了。

cookie 的转发

在处理中还发现我们的接口请求头中使用了 cookie 进行接口校验,每次请求都得带着校验信息。http-proxy-middleware配置项里提供了 request 和 response 相关处理函数,我们把服务器返回的 cookie 复制到代理请求上就可以了,简单代码如下:

var cookie = null

var options = {
  onProxyReq(proxyReq) {
    // 将本地请求的头信息复制一遍给代理。
    // 包含cookie信息,这样就能用登录后的cookie请求相关资源
    if (cookie) {
      proxyReq.setHeader('cookie', cookie)
    }
  },
  onProxyRes(proxyRes) {
    // 将服务器返回的头信息,复制一遍给本地请求的响应。
    // 这样就能实现 执行完登录后,本地的返回请求中也有相关cookie,从而实现登录功能代理。
    var proxyCookie = proxyRes.headers['set-cookie']
    if (proxyCookie) {
      cookie = proxyCookie
    }
  }
}

最终配置如下

const express = require('express')
const { createProxyMiddleware } = require('http-proxy-middleware')

const args = process.argv.splice(2)

// 本地调试的时候target设置为本地,默认为远程测试服务器
var target = 'http://X.X.X.X:XX'
if (args.length > 0 && args.includes('localhost')) {
  target = 'http://localhost:XX'
}

// 接口代理
var cookie = null
const options = {
  target,
  changeOrigin: true, //处理跨域
  onProxyReq(proxyReq) {
    // 将本地请求的头信息复制一遍给代理。
    // 包含cookie信息,这样就能用登录后的cookie请求相关资源
    if (cookie) {
      proxyReq.setHeader('cookie', cookie)
    }
  },
  onProxyRes(proxyRes) {
    // 将服务器返回的头信息,复制一遍给本地请求的响应。
    // 这样就能实现 执行完登录后,本地的返回请求中也有相关cookie,从而实现登录功能代理。
    var proxyCookie = proxyRes.headers['set-cookie']
    if (proxyCookie) {
      cookie = proxyCookie
    }
  },
  logLevel: 'debug' //string, 可选['debug', 'info', 'warn', 'error', 'silent'],默认值'info'
}

// 代理规则:https://github.com/chimurai/http-proxy-middleware#readme
const pathRule = ['**/*.do', '**/getAllRoles', '/boot/OA/**']

const apiProxy = createProxyMiddleware(pathRule, options)

const app = express()

// boot 的static前端目录路径,加一个/boot的虚拟地址因为前端中有些写了根据部署路径跳转
app.use('/boot', express.static('xxx/src/main/resources/static'))
app.use('/', apiProxy)

app.listen(3000, () => {
  console.log(`server is running on port ${3000}`)
})

如果后面还要需要代理的接口,直接往pathRule数组中添加代理规则就可以了。

总结

这里简单使用了 http-proxy-middleware对一些接口进行请求的转发,通过这不到50行的代码,我们把前后端开发解耦了,前端开发不再依赖于后端起的服务,我们可以随意的调整刷新就可以看到效果,虽然代码很简单,但是对开发效率还是有了一定的的提高,分享给同组的小伙伴后他们也用的很开心。工作上的事情能改进的还是应该去尝试一下,而不是大家都这么开发的,我为什么要去试试另外的方式呢,从来如此的,便对么?虽然是花费了你的时间,但是提高了团队的效率,这也算团队基建的一种吧。

后续也想集成webpack的HMR服务,但是一直没成功,鉴于维护工作已完成也就没有动力再去做这个了。