koa 2.0 - Middleware

  1. 1. 官方 middlewares 列表
  2. 2. 基本用法
  3. 3. middleware 原理
    1. 3.1. U型 嵌套 (洋葱嵌套)
    2. 3.2. 原理解析
  4. 4. V1 的支持方案
  5. 5. Middleware 能做的事
  6. 6. REF::

koa 2.0 系列:

Middleware 是 koa 里很重要的点,那关于 Middleware 的基本用法,实现原理和最终如何写一个 koa2 的中间件,大致的讲一下。


官方 middlewares 列表

这里是所有的 middleware 列表,支持 koa2 的不多,但也够用了,其实很多 middleware 真的就只是几句话的事,自己写也很方便。


基本用法

这个例子是从官方上改造的,加了总执行时长(x-response-time),并用到了以下特性:

  • koa2 context
  • async functions
  • arrow functions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
app.use(async (ctx, next) => {
// 启动 middleware,记录当前时间
let start = new Date;
// 进入下一个 middleware,并等待返回。
try {
await next() // next is now a function
} catch (err) {
ctx.body = { message: err.message }
ctx.status = err.status || 500
}
// 内部中间件执行完成,一般意味着业务执行完成。
// 这时,记录结束时间并输出。
let ms = new Date - start;
ctx.set('X-Response-Time', ms + 'ms');
})
// response
app.use(async ctx => {
// 这里处理业务,也就是最后的一个 middleware,所以不再调用 next()
const user = await User.getById(1) // await instead of yield
ctx.body = user // ctx instead of this
})


middleware 原理

U型 嵌套 (洋葱嵌套)

koa 最有特点的就是 U 型 middleware 的实现了,有点像面向切面编程 AOP 从上图可以看出,它顺序执行 middleware,到达最后一个时,又按队列再次顺序执行。

代码上理解就是这样子的:

1
2
3
4
5
6
7
8
9
10
11
12
.middleware1 {
// (1) do some stuff
.middleware2 {
// (2) do some other stuff
.middleware3 {
// (3) NO more middleware !
// ctx.body = 'hello world'
}
// (4) do some other stuff later
}
// (5) do some stuff lastest and return
}

原理解析

其实原理并不难,它是通过一个 compose 的库来实现这种的。


V1 的支持方案

koa2 已经不支持 generator 时代的 middleware,但提供了一个库来做转换 koa-convert,到 v3 时将彻底放弃。

1
2
3
4
import convert from 'koa-convert';
const app = new Koa();
app.use(convert(cors()));


Middleware 能做的事

  • 在请求到达前,做用户和权限的判断,做 RateLimit,限制 某个可用的 IP …
  • 在请求处理后,可以记录服务器处理时长,对结果统一格式化 ….

Express 的 Middleware 是单向的,就没有它这么方便。


REF::