Node框架koa中间件

body-parser

处理post请求的数据

    function bodyParser(ctx){
        return async (ctx,next)=>{
            await new Promise((resolve,reject)=>{
              let arr = [];
              ctx.req.on('data', function (chunk) {
                arr.push(chunk);
              });
              ctx.req.on('end', function () {
                if (ctx.get('Content-Type') === 'application/x-www-form-urlencoded'){
                  // a=1&b=2;
                  ctx.request.body = require("querystring").parse(Buffer.concat(arr).toString());
                }
                resolve();
              });
            });
            await next();
          }
    }
复制代码

better-body

处理post请求并且可以处理文件。

    function betterBody({uploadDir}) {
      return async (ctx,next)=>{
        await new Promise((resolve,reject)=>{
          let arr = [];
          ctx.req.on('data',function (chunk) {
            arr.push(chunk);
          })
          ctx.req.on('end',function () {
            let r = Buffer.concat(arr);
            // 文件上传类型
            let contentType = ctx.get('Content-Type');
            let fileds = {};
            if (contentType.startsWith('multipart/form-data')){
              let boundary = '--'+contentType.split('=')[1]; // 分隔符
              let lines = r.split(boundary).slice(1,-1);
              lines.forEach((line)=>{
                let [head,body] = line.split('\r\n\r\n');
                let h = head.toString(); // 头部信息
                if(h.includes('filename')){
                  // 文件  拿到文件内容后写入到真正的文件中
                  let content = line.slice(head.length + 4,-2);
                  // 需要一个文件名
                  let filename = `upload_${uuid.v1()}`;
                  fs.writeFileSync(path.resolve(__dirname, 'upload', filename), content);
                  fileds['file'] = filename;
                }else{
                  // 普通的输入框
                  let [,key] = h.match(/name="(.+?)"/);// 取出头部key
                  let value = body.toString().slice(0,-2); // 把内容取出来
                  fileds[key] = value;
                }
              })
            }
            ctx.request.fields = fileds;
            resolve();
          })
        });
        await next();
      }
    }
复制代码

koa-router

get方法将path和cb放到数组中保存,routes方法会找到path相同的来调用compose方法,越界的时候执行下一个中间件。

    class KoaRouter{
      constructor() {
        this.middles = [];
      }
      
      get(path,cb){
        this.middles.push({
          path,cb
        })
      }
      compose(routers, ctx, next){
        function dispatch(index) {
          if(index == routers.length) return next();
          let router = routers[index];
          router(ctx,()=>dispatch(index+1));
        }
        dispatch(0)
      }
      routes(){
        return async (ctx,next)=>{
          // 请求路径
          let pathname =  ctx.path;
          let routers = this.middles.filter(m=>m.path === pathname);
          // routers 是过滤出来的路径相同的路由
          // ctx 每次执行的时候 都需要上下文
          // next当越界时 应该调用下一个中间件
          routers = routers.map(router=>router.cb);
          this.compose(routers, ctx, next);
        }
      }
    }
    
    module.exports = KoaRouter;
复制代码

ejs模板

正则匹配+字符串拼接+new Function()(将字符串转换为函数)

    let fs = require('fs');
    let path = require('path');
    let templateStr = fs.readFileSync(path.join(__dirname, 'template.ejs'), 'utf8');
    
    function render(templateStr,obj) {
      // 我们拼接了一个大的字符串 并且用with来包裹 我需要让这个字符串执行
      let head = `with(obj){\r\n`;
      head += "var str = `";
      let content = templateStr.replace(/<%=(.*?)%>/g,function () {
        return "${"+arguments[1] +"}"
      })
      content = content.replace(/<%(.+?)%>/g,function () {
        return '`\r\n' + arguments[1] + '\r\nstr+=`'
      });
      let tail = '`\r\n} \r\n return str;';
      let total = head + content + tail;
      let fn = new Function('obj',total);
      return fn(obj);
    }
复制代码

views

    function views(dir) {
      return async (ctx,next)=>{
         ctx.render = function (p,obj) {
          return new Promise((resolve,reject)=>{
            let realPath =  path.resolve(dir, p);
            // 读取模板进行渲染
            fs.readFile(realPath,'utf8',function (err,data) {
              resolve(render(data, obj));
            })
          })
        }
        await next();
      }
    }
复制代码

koa-static

    function static(dir) {
      return async (ctx, next) => {
        // 先找当前目录下是否有这个文件,如果没有向下执行
        let p = path.join(dir, ctx.path);
        try{
          let statObj = await fs.stat(p);
          if (statObj.isFile()){
            ctx.set('Content-Type', `${mime.getType(p)};charset=utf8`);
            ctx.body = fs.createReadStream(p);
          }else{
            p = path.join(p,'index.html');
            await fs.access(p); // 判断有没有index.html 没有的话 会抛出异常
            ctx.set('Content-Type', `text/html;charset=utf8`);
            ctx.body = fs.createReadStream(p);
          }
        }catch(e){
          await next();
        }
      }
    }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值