Koa-router 优先级题目

题目形貌

在运用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路由先婚配中,路由也就不会往下婚配

处理体式格局

  1. 将前提更准确的路由放到前面
  2. /test谁人路由中加一个中间件,当婚配到/router/testawait next()继承向下实行
  3. 变动源码Router.propertype.usepath = "(.*)"path = false
  4. 在运用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
    原文作者:Leo_
    原文地址: https://segmentfault.com/a/1190000009635991
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞