koa 2.0 - Middleware

  1. 1. middleware 原理
    1. 1.1. U型 嵌套 (洋葱嵌套)
    2. 1.2. 原理解析

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::