* @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









