router源码学习小结(2)

/** * Create and register a route. * * @param {String} path Path string. * @param {Array.<String>} methods Array of HTTP verbs. * @param {Function} middleware Multiple middleware also accepted. * @returns {Layer} * @private */ Router.prototype.register = function (path, methods, middleware, opts) { opts = opts || {}; var router = this; // layer实例数组,初始为空数组 var stack = this.stack; // support array of paths if (Array.isArray(path)) { // 如果是多路径,递归注册路由 path.forEach(function (p) { router.register.call(router, p, methods, middleware, opts); }); return this; } // create route var route = new Layer(path, methods, middleware, { end: opts.end === false ? opts.end : true, name: opts.name, sensitive: opts.sensitive || this.opts.sensitive || false, strict: opts.strict || this.opts.strict || false, prefix: opts.prefix || this.opts.prefix || "", ignoreCaptures: opts.ignoreCaptures }); // 设置前置路由 if (this.opts.prefix) { route.setPrefix(this.opts.prefix); } // add parameter middleware Object.keys(this.params).forEach(function (param) { // 将router中this.params维护的参数中间件挂载到layer实例中 route.param(param, this.params[param]); }, this); // 所有layer实例存放在router的stack属性中 stack.push(route); return route; };

Router.prototype.match

/** * Match given `path` and return corresponding routes. * * @param {String} path * @param {String} method * @returns {Object.<path, pathAndMethod>} returns layers that matched path and * path and method. * @private */ Router.prototype.match = function (path, method) { // layer实例组成的数组 var layers = this.stack; var layer; var matched = { path: [], pathAndMethod: [], route: false }; for (var len = layers.length, i = 0; i < len; i++) { layer = layers[i]; debug('test %s %s', layer.path, layer.regexp); // 1.匹配路由 if (layer.match(path)) { matched.path.push(layer); // 2.匹配http请求方法 if (layer.methods.length === 0 || ~layer.methods.indexOf(method)) { matched.pathAndMethod.push(layer); // 3.指定了http请求方法,判定为路由匹配成功 if (layer.methods.length) matched.route = true; } } } return matched; };

Router.prototype.routes

/** * Returns router middleware which dispatches a route matching the request. * * @returns {Function} */ Router.prototype.routes = Router.prototype.middleware = function () { var router = this; var dispatch = function dispatch(ctx, next) { debug('%s %s', ctx.method, ctx.path); // 请求路由 var path = router.opts.routerPath || ctx.routerPath || ctx.path; // 将注册路由和请求的路由进行匹配 var matched = router.match(path, ctx.method); var layerChain, layer, i; if (ctx.matched) { ctx.matched.push.apply(ctx.matched, matched.path); } else { ctx.matched = matched.path; } ctx.router = router; // route属性是三次匹配的结果,表示最终是否匹配成功 if (!matched.route) return next(); // 同时满足路由匹配和http请求方法的layer数组 var matchedLayers = matched.pathAndMethod // 匹配多个路由时认为最后一个是匹配有效的路由 var mostSpecificLayer = matchedLayers[matchedLayers.length - 1] ctx._matchedRoute = mostSpecificLayer.path; if (mostSpecificLayer.name) { ctx._matchedRouteName = mostSpecificLayer.name; } // 将匹配的路由reduce为一个数组 layerChain = matchedLayers.reduce(function(memo, layer) { // 执行注册路由中间件之前,对context中的一些参数进行设置 memo.push(function(ctx, next) { // :path/XXX 捕获的路径 ctx.captures = layer.captures(path, ctx.captures); // 捕获的路径上的参数, { key: value } ctx.params = layer.params(path, ctx.captures, ctx.params); // 路由名称 ctx.routerName = layer.name; return next(); }); // 返回路由中间件的数组 return memo.concat(layer.stack); }, []); // 处理为promise对象 return compose(layerChain)(ctx, next); }; dispatch.router = this; return dispatch; };

Router.prototype.allowedMethod

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/1690e3f2cd69f10ca1d18c4f9e7fcd5f.html