koa-statickoa-static可以处理静态资源。参数为静态资源文件夹路径。官方实现包括更多的参数配置。具体可以参考koajs/static实现分析:获取请求url路径,找到static文件夹下的路径是否匹配如果路径是文件夹,则寻找文件夹下的index.html文件设置响应头文件类型(mime)gzip压缩,设置压缩类型并返回可读流错误或文件不存在next继续下一个中间件constfs=require("fs")constpath=require("path")constmime=require("mime")constzlib=require("zlib")functionstatic(dir){returnasync(ctx,next)=>{try{letreqUrl=ctx.path让abspath=path.join(dir,reqUrl)letstatObj=fs.statSync(abspath)//如果是文件夹,拼接index.htmlif(statObj.isDirectory()){abspath=path.join(abspath,"index.html")}//判断是否是路径是准确的fs.accessSync(abspath);//设置文件类型ctx.set("Content-Type",mime.getType(abspath)+";charset=utf8")//客户端允许的编码格式,判断是否需要gzip压缩constencoding=ctx.get("accept-encoding")if(/\bgzip\b/.test(encoding)){ctx.设置(“内容编码”,“gzip”)ctx.body=fs.createReadStream(abspath).pipe(zlib.createGzip())}elseif(/\bdeflate\b/.test(encoding)){ctx.set("内容编码","bdeflate")ctx.body=fs.createReadStream(abspath).pipe(zlib.createDeflate())}else{ctx.body=fs.createReadStream(abspath)}}catch(error){awaitnext()}}}module.exports=statickoa-bodyparserkoa-bodyparser可以处理POST请求数据并将form-data数据解析成ctx.request.body,官方地址:koa-bodyparser实现分析:读取请求数据,设置响应头类型application/json,判断客户端请求头content-type类型,解析数据并绑定到ctx.request.bodyfunctionbodyParser(){returnasync(ctx,next)=>{awaitnewPromise((resolve,reject)=>{letdata=[]ctx.req.on("data",(chunk)=>{data.push(chunk)})ctx.req.on("end",()=>{letct=ctx.get("content-type")letbody={}ctx.set("Content-Type","application/json")如果(ct==="application/x-www-form-urlencoded"){body=require("querystring").parse(Buffer.concat(data).toString())}if(ct==="application/json"){body=JSON.parse(Buffer.concat(data).toString())}ctx.request.body=bodyresolve()})ctx.req.on("error",(error)=>{reject(error)})})awaitnext()}}module.exports=bodyParserkoa-routerkoa-router允许koa像express一样控制路由,源码koa-router实现是比较复杂,这里实现一个简单的版本。实现分析:先把request保存到middlewares数组,routes返回middleware函数,从middlewares数组中获取ctx和next过滤掉相同路径/方法的数据中间件处理,传入ctx和封装好的next,调用处理完成后真正的nextmethodclassRouter{constructor(){//保存中间件方法数组this.middlewares=[]}get(path,handler){//get,post,delete,putmust被处理,只在这里实现getthis.middlewares.push({path,handler})}compose(routes,ctx,next){//调度每个存储的中间件方法constdispatch=(index)=>{//执行上下文只有在next处理完成后if(routes.length===index)returnnext();//将中间件的next包裹到下一个执行dispath中,防止context的next方法多次执行routes[index].handler(ctx,()=>dispatch(++index))}dispatch(0)}routes(){returnasync(ctx,next)=>{//过滤掉相同的存储对象letroutes=this.middlewares.filter((item)=>item.path===ctx.url)this.compose(routes,ctx,next)}}}module.exports=Router;koa-better-body使用koa-better-body处理koa-better-body中的文件上传,这里需要保证表单包含multipart/form-data:
