当前位置: 首页 > 后端技术 > Node.js

Koa系列——如何编写自己的Koa中间件

时间:2023-04-03 15:37:53 Node.js

Koa是Express原班人马打造的全新Web框架。Koa本身不捆绑任何中间件,只提供应用(Application)和上下文(Context)、请求(Request)、响应(Response)四个模块。Express中原有的路由器(Router)模块已经被移除,取而代之的是中间件。与Express相比,Koa更大程度上允许用户构建个性化的应用。一、中间件介绍Koa是一个中间件框架,本身不捆绑任何中间件。本身支持的功能不多,所有功能都可以通过中间件扩展实现。通过添加不同的中间件来构建Koa应用程序,以实现不同的需求。Koa的中间件是函数,可以是异步函数,也可以是普通函数。下面是官网上的例子://asyncfunctionapp.use(async(ctx,next)=>{conststart=Date.now();awaitnext();constms=Date.now()-start;console.log(`${ctx.method}${ctx.url}-${ms}ms`);});//普通函数app.use((ctx,next)=>{conststart=Date.now();returnnext().then(()=>{constms=Date.now()-start;console.log(`${ctx.method}${ctx.url}-${ms}ms`);});});中间件可以通过官方维护的仓库找到,也可以根据需要自己写中间件。2.中间件原理2.1例子下面是一个Koa应用,简单演示了中间件的执行顺序:constKoa=require('Koa');constapp=newKoa();//最外层的中间件app.use(async(ctx,next)=>{awaitconsole.log(`1stexecution`);awaitnext();awaitconsole.log(`8thexecution`);});//二层中间件app.use(async(ctx,next)=>{awaitconsole.log(`第二次执行`);awaitconsole.log(`第三次执行`);awaitnext();awaitconsole.log(`第6次执行`);awaitconsole.log(`第6次执行`);log(`the7thexecution`);});//最里面的中间件app.use(async(ctx,next)=>{awaitconsole.log(`the4thexecution`);ctx.body="Helloworld.";awaitconsole.log(`第5次执行`);});app.listen(3000,()=>{console.log(`服务器端口为3000.`);})2.2原理从中可以看出上面的例子,中间件的执行顺序并不是从头到尾,而是类似于前端的事件流程。事件流是先捕获事件,到达目标,再进行事件冒泡。中间件的实现过程也是一样的。首先从最外层的中间件开始执行,然后进入next()之后的下一个中间件,一路执行到最内层的中间件,再从最内层的中间件开始执行。Koa中间件采用洋葱圈模型。每次执行next中间件,都会传入两个参数ctx和next。参数ctx是一个变量,封装了koa传入的request和response,通过它可以访问到request和response。next是进入下一个要执行的中间件。3、自己编写中间件3.1单独开发token校验中间件。我们经常使用JWT进行身份验证。token一般放在HTTP请求中的HeaderAuthorization字段中,每次请求都要后端验证。比如Java的Spring框架可以在Filter中对token进行统一校验,而Koa则是通过编写中间件来实现token校验。//token.js//令牌中间件module.exports=(options)=>async(ctx,next){try{try{//获取令牌consttoken=ctx.header.authorizationif(token){try{//验证function验证token并获取用户相关信息awaitverify(token)}catch(err){console.log(err)}}//进入下一个中间件awaitnext()}catch(err){console.log(err)}}//app.js//引入令牌中间件constKoa=require('Koa');constapp=newKoa();consttoken=require('./token')app.use(token())app.listen(3000,()=>{console.log(`Serverportis3000.`);})3.2log的中间件日志模块也是该行不可或缺的一部分。完善的日志系统可以帮助我们快速排查线上问题。通过koa中间件,我们可以实现自己的日志模块//logger.js//logger中间件constfs=require('fs')module.exports=(options)=>async(ctx,next)=>{conststartTime=Date.now()constrequestTime=newDate()awaitnext()constms=Date.now()-startTime;letlogout=`${ctx.request.ip}--${requestTime}--${ctx.method}--${ctx.url}--${ms}ms`;//输出日志文件fs.appendFileSync('./log.txt',logout+'\n')}//app.js//引入logger中间件constKoa=require('Koa');constapp=newKoa();constlogger=require('./logger')app.use(logger())app.listen(3000,()=>{console.log(`Serverportis3000.`);})可以结合log4js等包记录更详细的日志4.综上所述,我们了解了中间件的原理以及如何实现一个自己的中间件。中间件的代码通常比较简单。我们可以通过阅读官方维护的仓库中优秀中间件的源码来加深对中间件的理解和应用。