资讯专栏INFORMATION COLUMN

Koa-router 优先级问题

Paul_King / 1180人阅读

摘要:问题描述在使用作为路由遇到了一个优先级问题如下代码在访问时路由会优先匹配到路由返回这个问题就很尴尬了项目空闲下来去翻看源码终于找到了原因问题原因的源码并不长和两个文件加起来共一千多行代码建议可以结合这篇文章阅读其中造成这个问题的原因

问题描述

在使用Koa-router作为路由遇到了一个优先级问题.如下代码

// routerPage.js file
const router = require("koa-router")
router.get("/test", ctx => { ctx.body = "test" })
router.get("/router/test", ctx => { ctx.body = "router test" })
module.exports = router

// routerIndex.js file
const router = require("koa-router")
const routerPage = require("./routerPage")
router.use(routerPage.routes(), routerPage.allowedMethods())
module.exports = router

在访问"/router/test"时路由会优先匹配到"/test"路由,返回ctx.body = "test",这个问题就很尴尬了,项目空闲下来去翻看源码终于找到了原因

问题原因

Koa-router的源码并不长,layer.js和router.js两个文件加起来共一千多行代码.建议可以结合这篇文章阅读.
其中造成这个问题的原因就是router.js中router.use这个方法,方法源码如下

// 主要作用: 给path添加中间件
Router.prototype.use = function () {
  var router = this;
  var middleware = Array.prototype.slice.call(arguments);
  var path = "(.*)";

  // 如果path为array则递归调用use方法
  if (Array.isArray(middleware[0]) && typeof middleware[0][0] === "string") {
    middleware[0].forEach(function (p) {
      router.use.apply(router, [p].concat(middleware.slice(1)));
    });

    return this;
  }
  //如果传入了path,则只对此path操作
  var hasPath = typeof middleware[0] === "string";
  if (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 {
      router.register(path, [], m, { end: false, ignoreCaptures: !hasPath });
    }
  });

  return this;
};

问题就出在router.use(routerPage.routes(), routerPage.allowedMethods())时没有设置前缀,
路由就自动添加了默认的前缀"(.*)",这里的path发生了改变,在路由后续的操作中,将path使用pathToRegExp转换成正则表达式时"/test"这个path本应该是/^/test...../就会变成/(.*)//test...(大概是这个意思)
那么原本以/test开头的路由就会匹配包含/test的路由
所以request path 为/router/test时会被/test路由先匹配中,路由也就不会往下匹配

解决方式

将条件更精确的路由放到前面

/test那个路由中加一个中间件,当匹配到/router/testawait next()继续向下执行

更改源码Router.propertype.usepath = "(.*)"path = false

在使用router.use时代码做一定更改,代码如下

// routerPage.js file
const router = require("koa-router")
router.get("test", ctx => { ctx.body = "test" })
router.get("router/test", ctx => { ctx.body = "router test" })
module.exports = router

// routerIndex.js file
const router = require("koa-router")
const routerPage = require("./routerPage")
router.use("/", routerPage.routes(), routerPage.allowedMethods())
module.exports = router

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88300.html

相关文章

  • iKcamp团队制作|基于Koa2搭建Node.js实战(含视频)☞ 路由koa-router

    路由koa-router——MVC 中重要的环节:Url 处理器 ?? iKcamp 制作团队 原创作者:大哼、阿干、三三、小虎、胖子、小哈、DDU、可木、晃晃 文案校对:李益、大力萌、Au、DDU、小溪里、小哈 风采主播:可木、阿干、Au、DDU、小哈 视频剪辑:小溪里 主站运营:给力xi、xty 教程主编:张利涛 视频地址:https://www.cctalk.com/v/151...

    netmou 评论0 收藏0
  • 用Decorator控制Koa路由

    摘要:本文首发于用控制路由在中长这样还有上的框架两者都用来控制路由,这样写的好处是更简洁更优雅更清晰。反观或上的路由完全差了一个档次从开始就有了,只是浏览器和都还没有支持。 本文首发于:用Decorator控制Koa路由 showImg(https://segmentfault.com/img/remote/1460000015348698); 在Spring中Controller长这样 @...

    Hwg 评论0 收藏0
  • koa源码阅读[2]-koa-router

    摘要:第三篇,有关生态中比较重要的一个中间件第一篇源码阅读第二篇源码阅读与是什么首先,因为是一个管理中间件的平台,而注册一个中间件使用来执行。这里写入的多个中间件都是针对该生效的。 第三篇,有关koa生态中比较重要的一个中间件:koa-router 第一篇:koa源码阅读-0 第二篇:koa源码阅读-1-koa与koa-compose koa-router是什么 首先,因为koa是一个管...

    oneasp 评论0 收藏0
  • koa-rapid-router超越koa-router性能的100多倍

    摘要:我们分别使用这样的原则来测试向每个架构注入个静态路由,测试最末尾的那个。而我们如何做到达到的性能,主要我们在内存中维护了一份静态路由列表,能让程序以最快的速度找到我们需要的。 对比 如果使用nodejs来搭建Service服务,那么我们首选express或者koa,而fastify告诉我们一个数据: Framework Version Router? Requests/sec ...

    Mike617 评论0 收藏0
  • koa-router 源码浅析

    摘要:代码结构执行流程上面两张图主要将的整体代码结构和大概的执行流程画了出来,画的不够具体。那下面主要讲中的几处的关键代码解读一下。全局的路由参数处理的中间件组成的对象。 代码结构 showImg(https://segmentfault.com/img/remote/1460000007468236?w=1425&h=1772); 执行流程 showImg(https://segmentf...

    SillyMonkey 评论0 收藏0

发表评论

0条评论

Paul_King

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<