使用Egg.js做一个简易的api网关

5,687 阅读3分钟

网关提供了什么?

  1. 统一登录
  2. 反向代理
  3. web服务器
  4. 接口拦截

以上是我根据项目需求已经实现了的功能,后续还可以扩展一些其他功能: 灰色发布等。

背景

开发环境时防止跨域会在webpack中添加proxyTable配置,这个配置只在开发环境生效。等到了生产环境会单独启一个Express服务提供web静态资源和proxyTable。

也就是说,每个应用都会有一个Express服务,当应用多了以后不利于管理,部署麻烦。

我是如何实现的

egg服务的中间件

cors Middleware

egg-cors插件内置中间件,该中间件用于支持处理跨域请求

static Middleware

egg-static插件内置中间件,该中间件用于对外提供静态资源

multiApplicationStatic Middleware

egg-multi-application-static针对多应用映射不同的静态资源路径。使用koa-static插件实现,并将封装为插件

  • prefix 域名
  • dir 静态入口路径

源码解析

  1. 遍历配置项

  2. 取出来源域名与配置项的prefix对比

    满足:则取出配置项的dir生成一个提供静态资源服务的中间件并返回。

    不满足:返回next()

  3. 利用compose工具函数形成洋葱圈式的调用并返回

bodyParser Middleware

会解析请求体中的参数并添加到request对象中,当经过该插件解析后的请求再做proxy时可能会丢失post参数,所以这里要过滤一下:

如果访问路径是网关自己路由的话则解析,否则跳过

需要注意该中间件的顺序,当post请求被该中间件处理后,再做proxy可能会丢失参数

securities Middleware

egg-security预防与处理XSS(跨站脚本攻击)。

permissions Middleware

验证token及刷新token。

源码解析

  • 有token
    1. 验证token是否有效,无效则返回401
    2. 请求路径为/gateway/login/时直接跳回refererS地址或者提示已登录,refererS不存在
    3. 更新cookie.refererS有效时间
    4. 更新cookie.token有效时间
  • 无token
    1. 来源域是否已注册,未注册则返回401Application not register!
    2. 请求路径为/gateway/login时则设置cookie.refererS
    3. 请求路径是否需要登录,需要则返回401Request path not authorized!
  • 上面流程无return时则return next()函数

proxy Middleware

针对config.proxy中配置的域名及路径进行反向代理。

先判断请求来源的域名是否在config.proxy中,若条件满足则取出该域名下的配置,配合http-proxy-middlewarekoa-connect插件进行代理与响应。

一个请求解析的过程

  1. 进入multiApplicantionStatic中间件,判断是否为静态资源
  2. 进入 permissions中间件, 验证token是否合法
  3. 进入proxy中间件, 根据config的配置进行转发请求
  4. 交由egg-router处理

PS

大佬请轻喷, 直接从笔记里copy的,可能就我自己能看懂 - -。