Servite 默认会把 src/server/middlewares/
下的文件当做中间件。可以通过 defineMiddleware
来定义中间件:
import { defineMiddleware } from 'servite/runtime/server';
export default defineMiddleware(async (event, next) => {
// ... do something on request
await next(); // call next middleware
// ... do something before response
});
中间件的执行顺序是由文件的顺序决定的,并且有点类似于 Koa 的洋葱模型: 一个请求到达服务器时,会首先从外向内经过每一层中间件,到达核心处理器后,再由内向外依次经过相同的中间件。
例如,文件目录结构如下所示:
<root>
└─ src # 源码目录
└─ server # 服务端源码目录
└─ middlewares # 中间件目录
├─ a.ts
├─ b.ts
└─ c.ts
那与之对应的中间件执行顺序是:
Request → a → b → c → Response
a ← b ← c ↩︎
为了使得中间件的执行顺序更为可控,推荐给文件名添加数字前缀,例如:0.name.ts
,1.name.ts
等。
但如果你有超过 10 个中间件,那么可以使用两位数字前缀,例如:00.name.ts
,01.name.ts
,
这样能容纳 100 个中间件,已经完全足够了。
如果想在中间件中提前响应请求,那么应该使用 send()
、event.node.res.end()
等方法来提前发送响应,这时候也可以去掉 await next()
的调用了。
import { defineMiddleware, send } from 'servite/runtime/server';
export default defineMiddleware(async (event, _next) => {
// 提前在中间件里发送响应
await send(event, 'some data');
});
在中间件中,如果没有调用 await next()
来执行下一个中间件,并且请求还没有被响应,那么请求将会一直处于 pending 的状态,这通常是代码逻辑错误导致的。