koa-router源码学习小结

2020-06-17 06:39:43易采站长站整理

koa 框架一直都保持着简洁性, 它只对 node 的 HTTP 模块进行了封装, 而在真正实际使用, 我们还需要更多地像路由这样的模块来构建我们的应用, 而 koa-router 是常用的 koa 的路由库. 这里通过解析 koa-router 的源码来达到深入学习的目的.

源码架构图

调用链路-routes()

HTTP请求调用流程

Usage


const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

router.get('/', async (ctx, next) => {
console.log('index');
ctx.body = 'index';
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000);

Router


function Router(opts) {
if (!(this instanceof Router)) {
return new Router(opts);
}

this.opts = opts || {};
this.methods = this.opts.methods || [
'HEAD',
'OPTIONS',
'GET',
'PUT',
'PATCH',
'POST',
'DELETE'
];

// 存放router.param方法指定的参数的中间件
this.params = {};
// 存放layer实例
this.stack = [];
};

Layer


function Layer(path, methods, middleware, opts) {
this.opts = opts || {};
this.name = this.opts.name || null;
this.methods = [];
// 存放path路径参数的一些属性,eg: /test/:str => { name: str, prefix: '/' ....}
this.paramNames = [];
// 存放该路由的中间件
this.stack = Array.isArray(middleware) ? middleware : [middleware];

methods.forEach(function(method) {
var l = this.methods.push(method.toUpperCase());
// 如果支持get请求,一并支持head请求
if (this.methods[l-1] === 'GET') {
this.methods.unshift('HEAD');
}
}, this);

// ensure middleware is a function
this.stack.forEach(function(fn) {
var type = (typeof fn);
if (type !== 'function') {
throw new Error(
methods.toString() + " `" + (this.opts.name || path) +"`: `middleware` "
+ "must be a function, not `" + type + "`"
);
}
}, this);

this.path = path;
// 将路由转为正则表达式
this.regexp = pathToRegExp(path, this.paramNames, this.opts);

debug('defined route %s %s', this.methods, this.opts.prefix + this.path);
};

给Router实例挂载HTTP方法


/**
* Create `router.verb()` methods, where *verb* is one of the HTTP verbs such
* as `router.get()` or `router.post()`.