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

koa2的中间件功能及应用

时间:2023-04-03 11:43:38 Node.js

最近因为开发自己的博客站点,学习了koa2的搭建,写了一些自己认为比较重要或者需要了解的koa2中间件的功能和使用场景。koa-router路由中间件下载npmikoa-router使用常用的使用方法。需要注意的是,引入的koa-router是一个方法,引入后需要执行。constKoa=require('koa');constapp=newKoa();constrouter=require('koa-router')();//配置路由url//默认urlrouter.get('/',async(ctx,next)=>{ctx.body='HelloWorld';});//自定义urlrouter.get('/hello/:name',async(ctx,next)=>{varname=ctx.params.name;ctx.response.body=\`

Hello,${name}!

\`;});//注册路由app.use(router.routes(),router.allowedMethods());也可以按需导入注册路由,可以注册多条路由。获取不同请求下收到的参数router.get通过ctx.query获取参数router.post通过ctx.request.body获取参数动态路由router.get('/:id',func)通过ctx.params获取参数遍历注册routerFirst导入nodejs中的fs模块,使用fs的readdirSync方法获取指定目录下的所有文件名,遍历导入路由模块并注册。constfs=require('fs');//fs.readdirSync获取指定目录下的所有文件名,遍历导入的路由模块并注册fs.readdirSync('./routes').forEach(route=>{letapi=require(\`./routes/${route}\`);app.use(api.routes(),api.allowedMethods());});otherapirouter.prefix(prefix)inkoa-routeraddurlPrefix设置初始化路由器实例的路径前缀router.prefix('/user');router.post('/login',function(ctx,next){...});//实际路径/user/loginrouter.use(url|[url1,url2,...],(ctx,next)=>{...})路由中间件使用场景:我们通常需要验证用户是否登录可以使用这个接口,如果每个接口都写一次验证,非常繁琐,难以维护。这时候我们就需要路由中间件先进行校验,然后再进行下面的操作。router.use第一个参数是需要使用中间件的路径或者由多个路径组成的数组(需要注意的是如果路由设置了url前缀,设置前缀后需要注册中间件,参数中的url不需要前缀)。router.use的第二个参数是一个函数,该函数传递了ctx和next两个参数,可以通过ctx验证权限后判断是否执行下一个调用接口。这里需要特别注意的是,函数next使用的时候需要加上await。如果不添加,接口会返回调用接口前的结果,前台无法获取到数据。//这是错误的app.use(function(ctx,next){ctx.set("Access-Control-Allow-Origin","\*");next();});//这是正确的应用程序。use(asyncfunction(ctx,next){ctx.set("Access-Control-Allow-Origin","\*");awaitnext();});koa-bodyparser在处理post请求的时候,我们会出现问题。无论是node的request对象还是koa的request对象,都没有办法解析出request的body。我们需要下载并引入一个中间件koa-bodyparser来解析body。koa-bodyparser的具体配置见后面的说明,这里我们直接放到使用方法中。//导入路由文件constindex=require('./routes/index.js');constuser=require('./routes/user.js');//导入解析request.body的中间件constbodyparser=require('koa-bodyparser');//注册bodyparser,需要注意的是bodyparser的注册必须在router路由之前注册app.use(bodyparser({enableTypes:\['json','form','text'\]}));...//注册路由app.use(index.routes(),index.allowedMethods());app.use(user.routes(),user.allowedMethods());koa-bodyparser同上上面说了koa-bodyparser是用来解析request.body的,因为node和koarequest是不能解析body的。下载npmikoa-bodyparser使用constbodyparser=require('koa-bodyparser');注册运行时,可以在bodyparser方法中传入对象,进行相应的配置。-enableTypes:解析器只在配置了enableTypes时解析请求类型,默认为['json','form']。-encoding:请求编码,默认为utf-8。-formLimit:如果主体最终大于此限制,则urlencoded主体的imit返回413错误代码。默认值为56kb。-jsonLimit:json体的限制。默认值为1mb。-textLimit:文本正文的限制。默认值为1mb。-strict:当设置为true时,JSON解析器将只接受数组和对象。默认为真。见文中的严格模式。在严格模式下,ctx.request。body始终是一个对象(或数组),避免了很多类型判断。但是文本文字总是返回字符串类型。-detectJSON:自定义json请求检测功能。默认为空。app.use(bodyparser({detectJSON:function(ctx){return/\\.json$/i.test(ctx.path);}}));-extendTypes:支持扩展类型app.use(bodyparser({extendTypes:{json:\['application/x-javascript'\]//将application/x-javascript类型解析为JSON字符串}}));-onerror:支持自定义错误处理器,如果koa-bodyparser抛出错误,你可以自定义响应如下:app.use(bodyparser({onerror:function(err,ctx){ctx.throw('bodyparseerror',422);}}));-disableBodyParser:可以通过设置ctxDisablebodyparser来动态设置。disableBodyParser=真。app.use(async(ctx,next)=>{if(ctx.path==='/disable')ctx.disableBodyParser=true;awaitnext();});app.use(bodyparser());koa-loggerrequestresponse监听日志下载npmikoa-loggeruse~~//引入日志中间件constlogger=require('koa-logger');//注册日志中间件app.use(logger());~~koa-sessionKoa的简单会话中间件。默认为基于cookie的会话,并支持外部存储。session我们知道http协议是无状态的。用户登录时,不会保存账号密码。如果我们需要维护用户的登录状态,我们需要使用一些方法。目前主流的用户认证方式有两种:token-based和session-based。koa-jwt中间件可以用于token-based认证,题目的koa-session可以用于session-based认证。下载npmikoa-session使用app.js入口文件注册sessionconstCONFIG={key:'koa:sess',/\*\*(string)cookiekey(defaultiskoa:sess)\*//\*\*(number||'session')maxAgeinms(defaultis1days)\*///保存状态的最长时间,默认为1天maxAge:86400000,autoCommit:true,/\*\*(boolean)自动保存headerPart(defaulttrue)\*/overwrite:true,/\*\*(boolean)是否覆盖(defaulttrue)\*/httpOnly:true,/\*\*(boolean)httpOnlyornot(defaulttrue)\*/signed:true,/\*\*(boolean)signedornot(defaulttrue)\*//\*\*(boolean)强制在每个会话标识符cookie上设置回复。过期会重置为原来的maxAge,过期倒计时也会重置。(defaultisfalse)\*/rolling:false,/\*\*(boolean)在会话即将到期时更新会话,这样我们就可以一直保持用户登录。(默认为false)\*/更新:false,};//如果你有所有的默认配置,你不需要传递配置参数,只是app.use(session(app))app.use(session(sessionConfig,app));session注册后,可以通过上下文ctx找到session属性。以下代码将用户信息存储在session属性中,并创建key和value{用户名:Joi.string().required(),密码:Joi.string().required(),})让结果=Joi。validate(data,schema)//如果有字段类型错误if(result.error){returnctx.response.body={status:400,msg:result.error.details};}let{username,password}=result.value//验证数据//判断用户是否存在constuserInfo=awaitusersModel.findByName(username)//如果用户存在,继续验证密码是否正确if(userInfo){constuserInfo2=awaitusersModel.findOne({username,password})if(userInfo2){ctx.response.body={state:200,msg:'loginsuccessful'}//设置会话ctx.session.userInfo=userInfo2}else{ctx.response.body={state:410,msg:'密码错误'}}//如果用户不存在,返回结果}else{ctx.response.body={state:410,msg:'用户不存在notexist'}}returnctx.response.body}在koa-router路由中间件中验证session。需要注意的是,await必须在next()方法之前使用,否则程序不会等待next()方法执行完毕。exportconstverifyUser=async(ctx,next)=>{if(ctx.session.userInfo){awaitnext()}else{returnctx.response.body={state:401,msg:'无权限'}}}koa2-cors用于解决跨域问题下载npminstallkoa2-cors使用app.use(cors())