问题描述我在使用koa-router做路由的时候遇到了一个优先级的问题。以下代码//routerPage.jsfileconstrouter=require("koa-router")router.get("/test",ctx=>{ctx.body="test"})router.get("/router/test",ctx=>{ctx.body="routertest"})module.exports=router//routerIndex.jsfileconstrouter=require("koa-router")constrouterPage=require("./routerPage")router.使用(routerPage.routes(),routerPage.allowedMethods())module.exports=当路由器访问“/router/test”时,路由会先匹配“/test”路由,返回ctx.body=“test”,这样问题很尴尬,项目随意浏览了源码终于找到了问题的原因。Koa-router的源码并不长,layer.js和router.js这两个文件加起来也就1000多行代码。推荐阅读这篇文章。出现这个问题的原因是router.js中的router.use方法。方法源码如下//主要功能:将中间件Router添加到路径中.prototype.use=function(){varrouter=this;varmiddleware=Array.prototype.slice.call(arguments);变量路径='(.*)';//如果路径是数组,则递归调用use方法(Array.isArray(middleware[0])&&typeofmiddleware[0][0]==='string'){middleware[0].forEach(function(p){router.use.apply(路由器,[p].concat(middleware.slice(1)));});归还这个;}//如果传入一个路径,则只对该路径进行操作varhasPath=typeofmiddleware[0]==='string';如果(hasPath){path=middleware.shift();}//如果传入参数是路由数组,则遍历为每条路由添加前缀和中间件,将这条路由放入全局路由数组中middleware.forEach(function(m){if(m.router){m.router.stack.forEach(function(nestedLayer){if(path)nestedLayer.setPrefix(path);if(router.opts.prefix)nestedLayer.setPrefix(router.opts.prefix);router.stack.push(nestedLayer);});if(router.params){Object.keys(router.params).forEach(function(key){m.router.param(key,router.params[key]);});}}else{路由器.register(path,[],m,{end:false,ignoreCaptures:!hasPath});}});返回这个;};问题出在router.use(routerPage.routes(),routerPage.allowedMethods())没有设置前缀,路由会自动加上默认前缀“(.*)”,这里的路径变了,在后续路由的操作,路径会使用pathToRegExp转换成正则表达式,路径“/test”应该是/^\/test...../,会变成/(.*)/\/测试...(可能意思是)那么原来以/test开头的路由会匹配到包含/test的路由,所以当请求路径为/router/test时,会优先匹配/test路由,不会向下匹配路由。解决方法是改变条件,将精确路由放在前面,在/test路由中添加一个中间件。当匹配到/router/test时,awaitnext()继续向下执行。将源码Router.propertype.use中的path="(.*)"改为path=false使用router.use时,需要更改代码,代码如下//routerPage.jsfileconstrouter=require("koa-router")router.get("test",ctx=>{ctx.body="test"})router.get("router/test",ctx=>{ctx.body="路由器测试"})module.exports=router//routerIndex.js文件constrouter=require("koa-router")constrouterPage=require("./routerPage")router.use("/",routerPage.routes(),routerPage.allowedMethods())module.exports=路由器
