Nodejs之koa

Koa

https://www.koajs.net/

https://koa.nodejs.cn/

  • Koa是一个由Express原班人马打造的,尝试在Web应用开发中摆脱回调地狱,并增强错误处理的轻量化的Node.js框架。
  • Koa的目标是成为一个更小、更富表现力、更健壮的Web框架。

安装

Koa需要Node v12或更高版本以支持ES2015和异步函数。 您可以使用您喜欢的版本管理器快速安装一个支持的Node版本:

nvm install 12
npm install koa
node my-koa-app.js

基本使用

Koa应用是一个包含中间件函数数组的对象,这些函数在请求时以类似堆栈的方式组合并执行

在Koa框架中,ctx 是上下文对象,它封装了原生的Node.js请求和响应对象,并且提供了许多方便的方法和属性来处理HTTP请求和响应

ctx.reqctx.res 是Node.js的原生请求和响应对象。这些对象提供了低级别的请求和响应处理方法

ctx.res.end('ok')` 是直接调用Node.js原生响应对象的 `end` 方法来结束响应并发送字符串 `ok

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

server.js

1.server.js

 // 导入koa模块
const Koa = require('./koa');
// 创建一个Koa应用实例
const app = new Koa(); 
app.use(function (ctx) {
  // 处理请求,返回'hello'
  ctx.res.end('hello'); 
});
// 监听3000端口,并在控制台打印服务器运行信息
app.listen(3000, () => console.log('server is running at http://localhost:3000'));

application.js

koa\lib\application.js

 // 导入http模块
const http = require('http');
module.exports = class Application {
    use(fn) {
        // 设置中间件处理函数
        this.middleware = fn; 
    }
    listen(...args) {
         // 创建一个HTTP服务器实例,并使用回调函数作为请求处理程序
        const server = http.createServer(this.callback());
         // 监听指定的端口,并返回监听器对象
        return server.listen(...args);
    }
    callback() {
        const handleRequest = (req, res) => {
             // 创建上下文对象
            const ctx = this.createContext(req, res);
            // 调用中间件处理函数
            this.middleware(ctx); 
        };
        // 返回请求处理函数
        return handleRequest; 
    }
    createContext(req, res) {
        //创建上下文对象
        const context = {};
        //设置请求对象
        context.req = req; 
        //设置响应对象
        context.res = res;
        //返回上下文对象
        return context;
    }
}

request&response

在Koa中,ctx.requestctx.response 是封装了 Node.js 原生请求和响应对象(ctx.reqctx.res)的对象。相比于 Node.js 的原生请求和响应对象,ctx.requestctx.response 提供了更多的方法和属性,使得处理 HTTP 请求和响应更加方便和简单。

  • ctx.request

    :

    • ctx.request.query: 一个包含解析过的查询字符串的对象
    • ctx.request.method: 请求方法,例如 ‘GET’, ‘POST’ 等
    • ctx.request.url: 请求的 URL
    • ctx.request.header: 请求头对象
    • ctx.request.body: 请求体(需要额外的中间件如koa-bodyparser来解析请求体)
  • ctx.response

    :

    • ctx.response.body: 可以设置响应体的内容,它可以是一个字符串、对象或者流
    • ctx.response.status: 可以设置响应的 HTTP 状态码
    • ctx.response.message: HTTP 状态消息
    • ctx.response.header: 响应头对象

server.js

// 引入Koa框架
const Koa = require('./koa');
// 实例化Koa对象
const app = new Koa();
// 使用中间件处理请求
app.use(async ctx => {
+  // 打印请求方法
+  console.log(ctx.request.method, ctx.method)
+  // 打印请求URL
+  console.log(ctx.request.url, ctx.url)
+  // 打印请求路径
+  console.log(ctx.request.path, ctx.path)
+  // 打印查询字符串参数
+  console.log(ctx.request.query, ctx.query)
+  // 打印请求头
+  console.log(ctx.request.header, ctx.header)
+  // 设置响应状态码
+  ctx.response.status = 200;
+  ctx.status = 200;
+  // 设置响应消息
+  ctx.response.message = 'OK';
+  ctx.message = 'OK';
+  ctx.set('Content-Type', 'text/html;charset=utf-8');
+  // 设置响应体
+  ctx.response.body = 'Hello';
+  ctx.body = 'Hello';
});
// 监听3000端口,启动服务
app.listen(3000, () => console.log('server is running at http://localhost:3000'));

application.js

koa\lib\application.js

// 导入http模块
const http = require('http');
// 导入自定义的context模块
const context = require('./context.js');
// 导入自定义的request模块
const request = require('./request');
// 导入自定义的response模块
const response = require('./response');
module.exports = class Application {
    // 构造函数
    constructor() {
        // 创建一个新的context对象,这个对象继承自自定义的context模块
        this.context = Object.create(context)
        // 创建一个新的request对象,这个对象继承自自定义的request模块
        this.request = Object.create(request)
        // 创建一个新的response对象,这个对象继承自自定义的response模块
        this.response = Object.create(response)
    }
    use(fn) {
        // 设置中间件处理函数
        this.middleware = fn;
    }
    listen(...args) {
        // 创建一个HTTP服务器实例,并使用回调函数作为请求处理程序
        const server = http.createServer(this.callback());
        // 监听指定的端口,并返回监听器对象
        return server.listen(...args);
    }
    callback() {
        const handleRequest = (req, res) => {
            // 创建上下文对象
            const ctx = this.createContext(req, res);
            // 调用中间件处理函数
            this.middleware(ctx);
            // 获取context对象的body属性
+           let body = ctx.body;
+           // 结束响应并发送body
+           return res.end(body);
        };
        // 返回请求处理函数
        return handleRequest;
    }
+   createContext(req, res) {
+       // 创建一个新的context对象,这个对象继承自this.context
+       const context = Object.create(this.context)
+       // 创建一个新的request对象,这个对象继承自this.request,并将这个对象赋值给context.request
+       const request = context.request = Object.create(this.request)
+       // 创建一个新的response对象,这个对象继承自this.response,并将这个对象赋值给context.response
+       const response = context.response = Object.create(this.response)
+       // 将原生的req和res对象赋值给context、request和response的req和res属性
+       context.req = request.req = req;
+       context.res = response.res = res;
+       // 返回创建的context对象
+       return context;
+   }
}

context.js

koa\lib\context.js

// 导入自定义的代理(delegate)模块
const delegate = require('./delegates')
// 创建一个空对象proto并将其导出
const proto = module.exports = {}
// 使用代理模块将proto对象的一些属性代理到'request'对象
delegate(proto, 'request')
    .access('method')  // 将'request'对象的'method'属性代理到proto对象
    .access('query')   // 将'request'对象的'query'属性代理到proto对象
    .access('url')     // 将'request'对象的'url'属性代理到proto对象
    .access('path')    // 将'request'对象的'path'属性代理到proto对象
    .getter('header')  // 将'request'对象的'header'属性的获取代理到proto对象
// 使用代理模块将proto对象的一些属性代理到'response'对象
delegate(proto, 'response')
    .access('status')  // 将'response'对象的'status'属性代理到proto对象
    .access('message') // 将'response'对象的'message'属性代理到proto对象
    .access('body')    // 将'response'对象的'body'属性代理到proto对象
    .method('set')     // 将'response'对象的'set'方法代理到proto对象

request.js

koa\lib\request.js

// 导入 parseurl 模块,用于解析 URL
const parse = require('parseurl')
// 导入 querystring 模块,用于解析查询字符串
const qs = require('querystring')
// 导出一个对象,这个对象定义了一些属性的 getter
module.exports = {
    // 获取 HTTP 请求的头部
    get header () {
        return this.req.headers
    },
    // 获取 HTTP 请求的 URL
    get url () {
        return this.req.url
    },
    get path () {
        return parse(this.req).pathname
    },
    // 获取 HTTP 请求的方法
    get method () {
        return this.req.method
    },
    // 获取 HTTP 请求的查询字符串
    get querystring () {
        return parse(this.req).query;
    },
    // 获取 HTTP 请求的查询参数,这些参数是一个对象,它由查询字符串解析得到
    get query () {
        return qs.parse(this.querystring)
    }
}

response.js

koa\lib\response.js

// 定义一个模块,暴露出一些属性和方法
module.exports = {
    // 设置状态码的方法
    set status(code) {
        this.res.statusCode = code;
    },
    // 设置状态消息的方法
    set message(msg) {
        this.res.statusMessage = msg;
    },
    // 设置body的方法
    set body(val) {
        this._body = val;
    },
    // 获取body的方法
    get body () {
        return this._body
    },
    set (field, val) {
        this.res.setHeader(field, val)
    }
}

delegates.js

koa\lib\delegates.js

// 定义一个Delegator函数,接收proto和target两个参数
function Delegator(proto, target) {
    // 如果当前函数不是通过new关键字调用的,那么就返回一个新的Delegator实例
    if (!(this instanceof Delegator)) return new Delegator(proto, target);
    // 将proto和target保存为Delegator实例的属性
    this.proto = proto;
    this.target = target;
}
// 在Delegator原型上定义一个access方法,这个方法接收一个name参数
Delegator.prototype.access = function (name) {
    // 调用getter和setter方法,将name属性的获取和设置代理到target对象
    return this.getter(name).setter(name);
};
// 在Delegator原型上定义一个getter方法,这个方法接收一个name参数
Delegator.prototype.getter = function (name) {
    // 保存proto和target属性
    var proto = this.proto;
    var target = this.target;
    // 在proto对象上定义一个name属性,这个属性的获取被代理到target对象
    Object.defineProperty(proto, name, {
        get: function () {
            return this[target][name];
        },
        configurable:true
    });
    // 返回当前Delegator实例
    return this;
};
// 在Delegator原型上定义一个setter方法,这个方法接收一个name参数
Delegator.prototype.setter = function (name) {
    // 保存proto和target属性
    var proto = this.proto;
    var target = this.target;
    // 在proto对象上定义一个name属性,这个属性的设置被代理到target对象
    Object.defineProperty(proto, name, {
        set: function (val) {
            this[target][name] = val;
        },
        configurable:true
    });
    // 返回当前Delegator实例
    return this;
};
Delegator.prototype.method = function(name){
    var proto = this.proto;
    var target = this.target;
    proto[name] = function(){
      return this[target][name].apply(this[target], arguments);
    };
    return this;
};
// 导出Delegator函数
module.exports = Delegator;

中间件级联

同步中间件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.server.js

const Koa = require('koa');
const app = new Koa();
const middleware1 = (ctx, next) => {
  console.log(1);
  next();
  console.log(2);
};
const middleware2 = (ctx, next) => {
  console.log(3);
  next();
  console.log(4);
};
const middleware3 = (ctx) => {
  console.log(5);
};
app.use(middleware1);
app.use(middleware2);
app.use(middleware3);
app.listen(3000, () => console.log('server is running at http://localhost:3000'));


(ctx, next) => {
  console.log(1);
  (ctx, next) => {
    console.log(3);
    (ctx) => {
      console.log(5);
    }
    console.log(4);
  }
  console.log(2);
}

异步中间件

img

server.js

const Koa = require('koa');
const app = new Koa();
const middleware1 = async (ctx, next) => {
  console.time('cost');
  console.log(1);
  await next();
  console.log(2);
  console.timeEnd('cost')
};
const middleware2 = async (ctx, next) => {
  console.log(3);
  await new Promise((resolve) => {
    setTimeout(() => {
      console.log('middleware2 sleep 1s');
      resolve();
    }, 1000);
  });
  await next();
  console.log(4);
};
const middleware3 = async (ctx) => {
  console.log(5);
  await new Promise((resolve) => {
    setTimeout(() => {
      console.log('middleware3 sleep 1s');
      resolve();
    }, 1000);
  });
  ctx.body = 'hello';
  console.log(6);
};
app.use(middleware1);
app.use(middleware2);
app.use(middleware3);
app.listen(3000, () => console.log('server is running at http://localhost:3000'));


1
3
middleware2 sleep 1s
5
middleware3 sleep 1s
6
4
2
cost: 2.022s

application.js

koa\lib\application.js

// 导入http模块
const http = require('http');
// 导入自定义的context模块
const context = require('./context.js');
// 导入自定义的request模块
const request = require('./request');
// 导入自定义的response模块
const response = require('./response');
+const compose = require('./koa-compose')
module.exports = class Application {
    // 构造函数
    constructor() {
        // 创建一个新的context对象,这个对象继承自自定义的context模块
        this.context = Object.create(context)
        // 创建一个新的request对象,这个对象继承自自定义的request模块
        this.request = Object.create(request)
        // 创建一个新的response对象,这个对象继承自自定义的response模块
        this.response = Object.create(response)
+       this.middleware = []
    }
    use(fn) {
        // 设置中间件处理函数
+       this.middleware.push(fn)
+       return this
    }
    listen(...args) {
        // 创建一个HTTP服务器实例,并使用回调函数作为请求处理程序
        const server = http.createServer(this.callback());
        // 监听指定的端口,并返回监听器对象
        return server.listen(...args);
    }
    callback() {
+       const fn = compose(this.middleware)
        const handleRequest = (req, res) => {
            // 创建上下文对象
            const ctx = this.createContext(req, res);
+           return this.handleRequest(ctx, fn);
        };
        // 返回请求处理函数
        return handleRequest;
    }
+   handleRequest(ctx, fnMiddleware) {
+       const handleResponse = () => respond(ctx);
+       return fnMiddleware(ctx).then(handleResponse);
+   }
    createContext(req, res) {
        // 创建一个新的context对象,这个对象继承自this.context
        const context = Object.create(this.context)
        // 创建一个新的request对象,这个对象继承自this.request,并将这个对象赋值给context.request
        const request = context.request = Object.create(this.request)
        // 创建一个新的response对象,这个对象继承自this.response,并将这个对象赋值给context.response
        const response = context.response = Object.create(this.response)
        // 将原生的req和res对象赋值给context、request和response的req和res属性
        context.req = request.req = req;
        context.res = response.res = res;
        // 返回创建的context对象
        return context;
    }
}
+function respond(ctx) {
+    let res = ctx.res;
+    let body = ctx.body;
+    return res.end(body);
+}

koa-compose.js

koa\lib\koa-compose.js

function compose(middleware) {
    return function (context) {
        function dispatch(i) {
            let fn = middleware[i];
            return Promise.resolve(fn(context, () => dispatch(i + 1)));
        }
        return dispatch(0);
    };
}
module.exports = compose;

错误处理

server.js

const Koa = require('./koa');
const app = new Koa();
const middleware1 = async (ctx, next) => {
 //throw new Error('middleware1 error');
 await next();
};
const middleware2 = async (ctx, next) => {
  throw new Error('middleware2 error');
};
app.use(middleware1);
app.use(middleware2);
app.listen(3000, () => console.log('server is running at http://localhost:3000'));

koa-compose.js

koa\lib\koa-compose.js

function compose(middleware) {
    return function (context) {
        function dispatch(i) {
            let fn = middleware[i];
+           if (!fn) return Promise.resolve()
+           try {
+               return Promise.resolve(fn(context, () => dispatch(i + 1)));
+           } catch (err) {
+               return Promise.reject(err)
+           }
        }
        return dispatch(0);
    };
}
module.exports = compose;

application.js

koa\lib\application.js

// 导入http模块
const http = require('http');
// 导入自定义的context模块
const context = require('./context.js');
// 导入自定义的request模块
const request = require('./request');
// 导入自定义的response模块
const response = require('./response');
const compose = require('./koa-compose')
module.exports = class Application {
    // 构造函数
    constructor() {
        // 创建一个新的context对象,这个对象继承自自定义的context模块
        this.context = Object.create(context)
        // 创建一个新的request对象,这个对象继承自自定义的request模块
        this.request = Object.create(request)
        // 创建一个新的response对象,这个对象继承自自定义的response模块
        this.response = Object.create(response)
        this.middleware = []
    }
    use(fn) {
        // 设置中间件处理函数
        this.middleware.push(fn)
        return this
    }
    listen(...args) {
        // 创建一个HTTP服务器实例,并使用回调函数作为请求处理程序
        const server = http.createServer(this.callback());
        // 监听指定的端口,并返回监听器对象
        return server.listen(...args);
    }
    callback() {
        const fn = compose(this.middleware)
        const handleRequest = (req, res) => {
            // 创建上下文对象
            const ctx = this.createContext(req, res);
            return this.handleRequest(ctx, fn);
        };
        // 返回请求处理函数
        return handleRequest;
    }
    handleRequest(ctx, fnMiddleware) {
        const handleResponse = () => respond(ctx);
+       const onerror = err => ctx.onerror(err)
+       return fnMiddleware(ctx).then(handleResponse).catch(onerror);
    }
    createContext(req, res) {
        // 创建一个新的context对象,这个对象继承自this.context
        const context = Object.create(this.context)
        // 创建一个新的request对象,这个对象继承自this.request,并将这个对象赋值给context.request
        const request = context.request = Object.create(this.request)
        // 创建一个新的response对象,这个对象继承自this.response,并将这个对象赋值给context.response
        const response = context.response = Object.create(this.response)
        // 将原生的req和res对象赋值给context、request和response的req和res属性
        context.req = request.req = req;
        context.res = response.res = res;
        // 返回创建的context对象
        return context;
    }
}
function respond(ctx) {
    let res = ctx.res;
    let body = ctx.body;
    return res.end(body);
}

context.js

koa\lib\context.js

// 导入自定义的代理(delegate)模块
const delegate = require('./delegates')
// 创建一个空对象proto并将其导出
const proto = module.exports = {
+   onerror(err) {
+       const { res } = this;
+       this.status = 500;
+       res.end(err.message)
+   }
}
// 使用代理模块将proto对象的一些属性代理到'request'对象
delegate(proto, 'request')
    .access('method')  // 将'request'对象的'method'属性代理到proto对象
    .access('query')   // 将'request'对象的'query'属性代理到proto对象
    .access('url')     // 将'request'对象的'url'属性代理到proto对象
    .access('path')    // 将'request'对象的'path'属性代理到proto对象
    .getter('header')  // 将'request'对象的'header'属性的获取代理到proto对象
// 使用代理模块将proto对象的一些属性代理到'response'对象
delegate(proto, 'response')
    .access('status')  // 将'response'对象的'status'属性代理到proto对象
    .access('message') // 将'response'对象的'message'属性代理到proto对象
    .access('body')    // 将'response'对象的'body'属性代理到proto对象
    .method('set')     // 将'response'对象的'set'方法代理到proto对象

multiple times

server.js

const Koa = require('./koa');
const app = new Koa();
const middleware1 = async (ctx, next) => {
+  await next(); 
+  await next();
};
const middleware2 = async (ctx, next) => {

};
app.use(middleware1);
app.use(middleware2);
app.listen(3000, () => console.log('server is running at http://localhost:3000'));

koa-compose.js

koa\lib\koa-compose.js

function compose(middleware) {
    return function (context) {
+       let index = -1;
        function dispatch(i) {
+           if (i <= index) return Promise.reject(new Error('next() called multiple times'));
+           index = i;
            let fn = middleware[i];
            if (!fn) return Promise.resolve()
            try {
                return Promise.resolve(fn(context, () => dispatch(i + 1)));
            } catch (err) {
                return Promise.reject(err)
            }
        }
        return dispatch(0);
    };
}
module.exports = compose;

body

server.js

const Koa = require('./koa');
const app = new Koa();
const fs = require('fs');
const middleware1 = async (ctx, next) => {
+ ctx.body = 'hello world';
+ //ctx.body = Buffer.from('hello world');
+ //ctx.body = fs.createReadStream('./package.json');
+ //ctx.body = {name:'hs'};
};
app.use(middleware1);
app.listen(3000, () => console.log('server is running at http://localhost:3000'));

application.js

koa\lib\application.js

// 导入http模块
const http = require('http');
// 导入自定义的context模块
const context = require('./context.js');
// 导入自定义的request模块
const request = require('./request');
// 导入自定义的response模块
const response = require('./response');
const compose = require('./koa-compose')
+const {Stream} = require('stream')
module.exports = class Application {
    // 构造函数
    constructor() {
        // 创建一个新的context对象,这个对象继承自自定义的context模块
        this.context = Object.create(context)
        // 创建一个新的request对象,这个对象继承自自定义的request模块
        this.request = Object.create(request)
        // 创建一个新的response对象,这个对象继承自自定义的response模块
        this.response = Object.create(response)
        this.middleware = []
    }
    use(fn) {
        // 设置中间件处理函数
        this.middleware.push(fn)
        return this
    }
    listen(...args) {
        // 创建一个HTTP服务器实例,并使用回调函数作为请求处理程序
        const server = http.createServer(this.callback());
        // 监听指定的端口,并返回监听器对象
        return server.listen(...args);
    }
    callback() {
        const fn = compose(this.middleware)
        const handleRequest = (req, res) => {
            // 创建上下文对象
            const ctx = this.createContext(req, res);
            return this.handleRequest(ctx, fn);
        };
        // 返回请求处理函数
        return handleRequest;
    }
    handleRequest(ctx, fnMiddleware) {
        const handleResponse = () => respond(ctx);
        const onerror = err => ctx.onerror(err)
        return fnMiddleware(ctx).then(handleResponse).catch(onerror);
    }
    createContext(req, res) {
        // 创建一个新的context对象,这个对象继承自this.context
        const context = Object.create(this.context)
        // 创建一个新的request对象,这个对象继承自this.request,并将这个对象赋值给context.request
        const request = context.request = Object.create(this.request)
        // 创建一个新的response对象,这个对象继承自this.response,并将这个对象赋值给context.response
        const response = context.response = Object.create(this.response)
        // 将原生的req和res对象赋值给context、request和response的req和res属性
        context.req = request.req = req;
        context.res = response.res = res;
        // 返回创建的context对象
        return context;
    }
}
function respond(ctx) {
+   let {res,body} = ctx;
+   if (Buffer.isBuffer(body)) return res.end(body)
+   if (typeof body === 'string') return res.end(body)
+   if (body instanceof Stream) return body.pipe(res)
+   res.end(JSON.stringify(body))
}

koa-static

server.js

const Koa = require('./koa');
const static = require('./koa-static');
const app = new Koa();
app.use(static(__dirname + '/static'));
app.listen(3000, () => console.log('server is running at http://localhost:3000'));

koa-static.js

koa-static.js

const { access } = require('fs/promises')
const { createReadStream } = require('fs')
const path = require('path')
module.exports = function (root) {
    return async function (ctx, next) {
        await next()
        if (!!ctx.body) return;
        const filename = path.join(root, ctx.path);
        if (await exists(filename)) {
            ctx.body = createReadStream(filename)
        }
    }
}
async function exists(path) {
    try {
        await access(path)
        return true
    } catch (e) {
        return false
    }
}

koa-bodyparser

server.js

const Koa = require('./koa');
const bodyparser = require('./koa-bodyparser');
const app = new Koa();
app.use(bodyparser());
app.use(async ctx => {
    if (ctx.url === '/' && ctx.method === 'GET') {
        // 显示表单页面
        let html = `
            <form method="POST" action="/">
                <p>userName</p>
                <input name="username"/><br/>
                <button type="submit">submit</button>
            </form>
        `;
        //设置响应头的类型text/html
        ctx.set('Content-Type', 'text/html;charset=utf-8');
        ctx.body = html;
    } else if (ctx.url === '/' && ctx.method === 'POST') {
        ctx.body = ctx.request.body;
    } else {
        ctx.body = '<h1>404!</h1>';
    }
});
app.listen(3000, () => console.log('server is running at http://localhost:3000'));

koa-bodyparser.js

koa-bodyparser.js

module.exports = function () {
    return async function bodyParser(ctx, next) {
        if (!!ctx.request.body)
            return await next();
        ctx.request.body = await parseBody(ctx.req);
        await next();
    };
};

function parseBody(req) {
    return new Promise((resolve) => {
        let buffers = [];
        req.on('data', chunk => {
            buffers.push(chunk);
        });
        req.on('end', () => {
            resolve(Buffer.concat(buffers).toString());
        });
    });
}

koa-router

server.js

server.js

const Koa = require('./koa');
const app = new Koa();
const Router = require('./koa-router.js');
const router = new Router();
router.get('/', async (ctx, next) => {
    ctx.body = 'Home';
    await next();
});
router.get('/user', async (ctx, next) => {
    ctx.body = 'User';
    await next();
});
app.use(router.routes());

app.listen(3000, () => console.log('server is running at http://localhost:3000'));

koa-router.js

koa-router.js

const methods = ['head', 'options', 'get', 'put', 'patch', 'post', 'delete'];
function Router() {
  this.stack = [];
}
for (const method of methods) {
  Router.prototype[method] = function (path, middleware) {
    this.stack.push({ path, method, middleware });
  };
}
Router.prototype.routes = function () {
  return async (ctx, next) => {
    const matched = this.stack.find(layer => {
      return layer.path === ctx.path && layer.method === ctx.method.toLowerCase();
    });
    if (!matched) return next();
    await matched.middleware(ctx, next);
  }
};
module.exports = Router;
  • 34
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值