官方描述:Egg 的中间件形式和 Koa 的中间件形式是一样的,都是基于洋葱圈模型。每次我们编写一个中间件,就相当于在洋葱外面包了一层。
它可以放在路由之前或者之后执行,不必进入到逻辑层做一进步的处理,减少代码的复杂和臃肿。比如说屏蔽IP,识别设备,过滤关键词等等。也可以在指定的路由中执行对应的中间件,非常的灵活。
编写屏蔽ip中间件
1,全局加载
首先编写中间件逻辑:
// app/middleware/banIP.ts export default function (options) { return async function banIP(ctx, next) { const banIPs = options.banIPs; const clientIp = ctx.request.ip; if (banIPs.indexOf(clientIp) != -1) { ctx.status = 403; ctx.body = 'ip已被屏蔽'; } else { await next(); } } }
然后在config里面配置中间件:
// config/config.default.ts // 添加中间件 config.middleware = ['banIP']; //屏蔽ip config.banIP = { banIPs: [ '127.0.0.1', '192.168.1.1' ] };
完成,客户端请求时ip在列表里就会返回403状态。
2,局部加载
这里的配置是全局的,只用所有客户端请求都会在中间件处理,也可以再指定接口做局部处理:
// app/router.ts import {Application} from 'egg'; export default (app: Application) => { const {controller, router} = app; const banIP = app.middleware.banIP({"banIPs": "127.0.0.1"}); // 获取房间列表 router.get('/api/room/list', controller.room.list); // 更新房间状态 router.post('/api/room/update', banIP, controller.room.update); };
然后在屏蔽config配置的中间件:
// config/config.default.ts // 添加中间件 // config.middleware = ['banIP'];
完成,现在获取房间列表接口可以正常访问,没有限制;更新房间状态还是会走屏蔽IP的中间件。
3,路由正则加载
另外,中间件可以匹配规则
// config/config.default.ts // 屏蔽ip config.banIP = { banIPs: [ '127.0.0.1', '192.168.1.1' ], match: ['/api/room'], // 只匹配指定路由,如果只忽略指定路由,可以用ignore };
路由:
// app/router.ts import {Application} from 'egg'; export default (app: Application) => { const {controller, router} = app; // 获取用户信息 router.get('/api/user/list', controller.user.list); // 获取房间列表 router.get('/api/room/list', controller.room.list); // 更新房间状态 router.post('/api/room/update', controller.room.update); };
完成,现在获取用户信息接口可以正常访问,没有限制;更新房间状态和房间列表接口会走屏蔽IP的中间件。