中间件写法
根据我们前文的分析,中间件通常为以下形式:
async (ctx, next) => {....}
复制代码
一般来说中间件有自己的配置,所以我们总结出来一种通用的中间件写法,我们通过传入配置的方式可以返回根据配置定制的中间件:
// 通用中间件写法
module.exports = function(options) {
// 配置处理
return aysnc (ctx, next) => {
// 中间件逻辑...
}
}
复制代码
使用方式:
app.use(middleware(options)) // middleware(options)返回一个中间件
复制代码
除此之外,还有另一种中间件写法。正如前文分析的一样,koa-compose可以将多个中间件合成一个中间件,那么我们也可将有关联的中间件合成一个大的中间件,写法如下:
app.use(compose([middleware1, middleware2, ...]))
复制代码
常见中间件
Koa是基于中间件模式的,但是框架本身并不包含任何中间件。在实际的开发当中,我们可以通过组合中间件进行功能的实现。Koa中常见的中间件如下:
- Koa-router:Koa-router的实现机制与koa本身的实现类似,都是分为两个阶段,初始化阶段和执行阶段。初始化阶段主要涉及到路由的注册,执行阶段为寻找到匹配的路由,然后使用compose函数合成一个中间件,执行该中间件。一个例子说明:
var Koa = require('koa');
var Router = require('koa-router');
var app = new Koa();
var router = new Router();
router.get('/', (ctx, next) => {}); // 注册路由
app.use(router.routes()) // 返回匹配路由的复合中间件
.use(router.allowedMethods());
复制代码
感兴趣的也可以参看源代码,简单易懂
- Koa-bodyparser 前文中讲过,node只会对header进行解析,header解析之后便发送一个request事件,body数据获取需要自己对req(incomingMessage)上的data和end事件进行监听。
const http = require('http');
http.createServer((req , res)=>{
console.log('request here.');
let data = '';
req.on('data',(chunk)=>{
data += chunk;
});
req.on('end',()=>{
console.log('data:',data);
});
}).listen(3000,'127.0.0.1');
复制代码
bodyparser中间件的作用就是获取body数据并按照想要的格式进行解析,将解析后的数据赋值给ctx.body。
app.use(bodyParser(options));
复制代码
- Koa-static:为静态资源访问创建一个服务器,根据url访问对应的文件夹、文件
- Koa-ejs:使用ejs渲染服务端模板
更多中间件请参考koa官方清单:https://github.com/koajs/koa/wiki
自己写中间件
说了这么多中间件,我们以自己写一个中间件作为该篇结束。以下示例为一个现实中的例子,做了一部分精简。问题的背景为,网站经常被某些ip攻击,影响业务正常运行,于是做了一个中间件进行ip的过滤,对于ip黑名单上的ip一律拒绝进一步处理请求。希望通过这个示例,能够使大家进一步了解中间件的作用。
/*
** iplimiter: ip过滤中间件,对于在ip黑名单上的ip直接返回,请求不再进行下去
** ip_blacklist: Array, example: ['192.123.12.11']
*/
module.exports = function(ip_blacklist) {
return async (ctx, next) => {
if(!Array.isArray(configs) && configs.length) {
let ip = ctx.request.headers['x-real-ip'] || '' //获取客户端ip,由于使用nginx作为负载均衡,所以获取ip的方式可通过x-real-ip字段
if(ip && ip_blacklist.indexOf(ip) !== -1) {
await next()
} else {
return res.end('ip restricted')
}
} else {
await next()
}
}
}
复制代码
也请大家关注我的知乎专栏,涨涨粉:知乎专栏:前端思考