egg.js 基于 Koa 实现,其中间件机制和 Koa 一样基于洋葱模型
编写中间件
写一个打印请求耗时的中间件
app/middleware/cost.js
async function cost(ctx, next) {
const now = Date.now();
await next();
ctx.set('X-Response-Time', `${Date.now() - now}ms`);
}
一般中间件都会有自己的配置,为了避免每次使用配置,egg.js 对中间件配置做了约定
- 中间件存放在 app/middleware/ 目录下
- 每个中间件需要使用一个方法包裹,并 export 出来,方法接收由框架传来的两个参数
- options:中间件的配置项,框架会把
app.config[middlwwareName]
传递进来 - app:当前的 application 实例
- options:中间件的配置项,框架会把
因此需要包装一下上面写的中间件
module.exports = (options, app) => {
return async function cost(ctx, next) {
const now = Date.now();
await next();
ctx.set('X-Response-Time', `${Date.now() - now}ms`);
};
};
中间件可以添加配置,允许开发者自定义响应头
module.exports = options => {
const header = options.header || 'X-Response-Time';
return async function cost(ctx, next) {
const now = Date.now();
await next();
ctx.set(header, `${Date.now() - now}ms`);
};
};
使用中间件
应用全局使用
如果希望中间件应用级生效,可以把中间件在 config 文件中开启
// config/config.${env}.js
config.middleware = ['cost'];
config.cost = {
header: 'egg-cost',
};
这样所有请求都会应用 cost 中间件,在响应头中使用 egg-const
输出响应时间
部分 router 使用
如果希望中间件只对单条路由生效,可以在路由中配置
const cost = app.middleware.cost({ header: 'egg-cost' });
app.get('/', cost, 'home.index');
通过规则配置
如果只希望某些特定规则的路由生效,一个个配置又十分麻烦,可以使用规则匹配,无论是应用层加载的中间件还是框架自带中间件,都支持几个通用的配置项:
- enable:控制中间件是否开启
- match:设置只有符合某些规则的请求才会经过这个中间件
- ignore:设置符合某些规则的请求不经过这个中间件
match 和 ignore 支持的参数都一样,只是作用完全相反,不允许同时配置。match 和 ignore 支持多种类型的配置方式// config/config.${env}.js
config.middleware = ['cost'];
config.cost = {
enable: true,
ignore: /^\/api/,
header: 'egg-cost',
}
- 字符串:当参数为字符串类型时,配置的是一个 url 的路径前缀,所有以配置的字符串作为前缀的 url 都会匹配上,也可以直接使用字符串数组
- 正则:当参数为正则时,直接匹配满足正则验证的 url 的路径
- 函数:当参数为一个函数时,会将请求上下文传递给这个函数,最终取函数返回的结果(true/false)来判断是否匹配
有关更多的 match 和 ignore 配置情况,详见 egg-path-matchingmatch(ctx) {
// 只有 ios 设备才开启
const reg = /iphone|ipad|ipod/i;
return reg.test(ctx.get('user-agent'));
},
使用 koa 中间件
因为同样使用洋葱模型,koa 中间件可以通过简单包装轻松引入 egg.js。以 koa-compress 为例,在 Koa 中使用时: ```javascript const koa = require(‘koa’); const compress = require(‘koa-compress’);
const app = koa();
const options = { threshold: 2048 }; app.use(compress(options));
在 egg.js 使用<br />_app/middleware/compress.js_
```javascript
// koa-compress 暴露的接口(`(options) => middleware`)和框架对中间件要求一致
module.exports = require('koa-compress');
config/config.default.js
module.exports = {
middleware: [ 'compress' ],
compress: {
threshold: 2048,
},
};