问题描述

在使用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

Koa-router 优先级问题相关推荐

  1. koa router ajax,ajax 请求 koa2 router.post 404

    我在页面用ajax请求一个路由,返回404, 该方法中使用了request模块调用了一个接口.我想原因可能是路由中request异步数据还没有返回,路由的方法就给返回了,怎么让该路由得到request ...

  2. generator探幽(1)--koa中间件机制浅析

    本系列旨在通过对co,koa等库源码的研究,进而理解generator在异步编程中的重大作用(ps:所有代码请在node --harmony或者iojs环境中运行) koa中间件的形式 相信用过koa ...

  3. 基于React+Koa实现一个h5页面可视化编辑器-Dooring

    前言 前段时间笔者一直忙于数据可视化方面的工作,比如如何实现拖拽式生成可视化大屏,如何定制可视化图表交互和数据导入方案等,这块需求在B端企业中应用非常大,所以非常有探索价值. 本篇文章并非和数据可视化 ...

  4. nodejs Koa框架及常用中间件

    目录 前言:了解nodejs 1.nodejs简介 2.nodejs安装 3.检验是否安装成功 4.npm介绍以及使用 ①.koa基础 1.koa创建简单实例 2.koa中间件 ②.koa中常用的第三 ...

  5. 浅析koa路由及其中间件

    文章目录 Koa路由 什么是路由? 路由的安装 路由的匹配 koa动态路由 中间件 什么是中间件 中间件的功能 应用级中间件 路由中间件 错误机制处理中间件 koa中间件的执行顺序--洋葱模型 Koa ...

  6. Node服务器 - koa框架

    1 koa的基本使用 2 koa的参数解析 3 koa响应和错误 4 koa静态服务器 5 koa的源码解析 6 和express对比 koa的基本使用过程 const Koa = require(' ...

  7. koa返回404 NOT FOUND

    使用koa router时,对某一接口获取数据,log打印时有实际数据,说明查询到了数据库内容,但koa的返回时404,这是koa的ctx没有进行操作时的默认返回. 最后发现这是koa的async和a ...

  8. Koa 学习 01 Koa 介绍和基本使用(路由、静态资源托管、中间件)

    Koa 介绍 Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造,致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 官网:https://k ...

  9. 小程序登录的正确打开方式

    小程序网络组件 RequestTask wx.request(Object object) RequestTask说明 方法 说明 RequestTask.abort() 中断请求任务. Reques ...

  10. 使用nodejs构建Docker image最佳实践

    文章目录 简介 准备nodejs应用程序 创建Dockerfile文件 创建.dockerignore文件 创建docker image 运行docker程序 node的docker image需要注 ...

最新文章

  1. DRF工程搭建、环境安装与配置
  2. 读《大规模敏捷开发实践》
  3. WPF:数据绑定--PropertyChangeNotification属性更改通知
  4. 【数据结构与算法】之深入解析“旋转链表”的求解思路与算法示例
  5. 聊一聊ABP vNext的模块化系统
  6. Leetcode--128. 最长连续序列
  7. JAVA类的无参方法
  8. ie不支持replaceall_继IE之后,微软又要彻底放弃这些office了
  9. Eclipse 使用的注意 灵格斯 取词
  10. Dreammail 下载与安装
  11. 商务网站建设与维护【15】
  12. SF18 | MACD顶底背离+动态区间交易模型源码(技术贴)
  13. c语言中的结构体定义和常见用法
  14. 万物皆可健身环:UP主爆改switch,用健身环玩起《塞尔达传说之旷野「喘」息》...
  15. 目前住院病人主要由护士护理,这样不仅需要大量护士,而且由于不能随时观察病人的病情变化,还可能会延误抢救时机。某医院打算开发一个以计算机为中心的监护系统,写出问题定义和分析系统可行性(软件工程导论)
  16. 64位32位 java 浏览器_Java编程语言下 Selenium 驱动各个浏览器代码
  17. Workbench螺栓连接的模拟方法
  18. 应用程序日志管理工具
  19. 新建Flutter项目
  20. HTTP报文是什么样的?

热门文章

  1. sublime配置markdown
  2. Drupal是如何避免页面缓存保存Message信息的
  3. CLRS2e读书笔记—Chapter10
  4. PL/SQL Developer 8注册码
  5. js实现倒计时的小例子
  6. 机器学习基础:朴素贝叶斯(Machine Learning Fundamentals: Naive Bayes)
  7. Android事件分发机制(一)
  8. (日常搬砖)windows 11 安装cython_bbox时,遇到问题‘error: Microsoft Visual C++ 14.0 or greater is required. ’解决方案
  9. Ubuntu 20.04 安装 php 并配置 OpenResty
  10. 【Flutter】Dart的方法中的可选参数、方法作为参数传递