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
路由先匹配中,路由也就不会往下匹配
解决方式
- 将条件更精确的路由放到前面
- 在
/test
那个路由中加一个中间件,当匹配到/router/test
时await next()
继续向下执行 - 更改源码
Router.propertype.use
中path = "(.*)"
为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
Koa-router 优先级问题相关推荐
- koa router ajax,ajax 请求 koa2 router.post 404
我在页面用ajax请求一个路由,返回404, 该方法中使用了request模块调用了一个接口.我想原因可能是路由中request异步数据还没有返回,路由的方法就给返回了,怎么让该路由得到request ...
- generator探幽(1)--koa中间件机制浅析
本系列旨在通过对co,koa等库源码的研究,进而理解generator在异步编程中的重大作用(ps:所有代码请在node --harmony或者iojs环境中运行) koa中间件的形式 相信用过koa ...
- 基于React+Koa实现一个h5页面可视化编辑器-Dooring
前言 前段时间笔者一直忙于数据可视化方面的工作,比如如何实现拖拽式生成可视化大屏,如何定制可视化图表交互和数据导入方案等,这块需求在B端企业中应用非常大,所以非常有探索价值. 本篇文章并非和数据可视化 ...
- nodejs Koa框架及常用中间件
目录 前言:了解nodejs 1.nodejs简介 2.nodejs安装 3.检验是否安装成功 4.npm介绍以及使用 ①.koa基础 1.koa创建简单实例 2.koa中间件 ②.koa中常用的第三 ...
- 浅析koa路由及其中间件
文章目录 Koa路由 什么是路由? 路由的安装 路由的匹配 koa动态路由 中间件 什么是中间件 中间件的功能 应用级中间件 路由中间件 错误机制处理中间件 koa中间件的执行顺序--洋葱模型 Koa ...
- Node服务器 - koa框架
1 koa的基本使用 2 koa的参数解析 3 koa响应和错误 4 koa静态服务器 5 koa的源码解析 6 和express对比 koa的基本使用过程 const Koa = require(' ...
- koa返回404 NOT FOUND
使用koa router时,对某一接口获取数据,log打印时有实际数据,说明查询到了数据库内容,但koa的返回时404,这是koa的ctx没有进行操作时的默认返回. 最后发现这是koa的async和a ...
- Koa 学习 01 Koa 介绍和基本使用(路由、静态资源托管、中间件)
Koa 介绍 Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造,致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 官网:https://k ...
- 小程序登录的正确打开方式
小程序网络组件 RequestTask wx.request(Object object) RequestTask说明 方法 说明 RequestTask.abort() 中断请求任务. Reques ...
- 使用nodejs构建Docker image最佳实践
文章目录 简介 准备nodejs应用程序 创建Dockerfile文件 创建.dockerignore文件 创建docker image 运行docker程序 node的docker image需要注 ...
最新文章
- DRF工程搭建、环境安装与配置
- 读《大规模敏捷开发实践》
- WPF:数据绑定--PropertyChangeNotification属性更改通知
- 【数据结构与算法】之深入解析“旋转链表”的求解思路与算法示例
- 聊一聊ABP vNext的模块化系统
- Leetcode--128. 最长连续序列
- JAVA类的无参方法
- ie不支持replaceall_继IE之后,微软又要彻底放弃这些office了
- Eclipse 使用的注意 灵格斯 取词
- Dreammail 下载与安装
- 商务网站建设与维护【15】
- SF18 | MACD顶底背离+动态区间交易模型源码(技术贴)
- c语言中的结构体定义和常见用法
- 万物皆可健身环:UP主爆改switch,用健身环玩起《塞尔达传说之旷野「喘」息》...
- 目前住院病人主要由护士护理,这样不仅需要大量护士,而且由于不能随时观察病人的病情变化,还可能会延误抢救时机。某医院打算开发一个以计算机为中心的监护系统,写出问题定义和分析系统可行性(软件工程导论)
- 64位32位 java 浏览器_Java编程语言下 Selenium 驱动各个浏览器代码
- Workbench螺栓连接的模拟方法
- 应用程序日志管理工具
- 新建Flutter项目
- HTTP报文是什么样的?
热门文章
- sublime配置markdown
- Drupal是如何避免页面缓存保存Message信息的
- CLRS2e读书笔记—Chapter10
- PL/SQL Developer 8注册码
- js实现倒计时的小例子
- 机器学习基础:朴素贝叶斯(Machine Learning Fundamentals: Naive Bayes)
- Android事件分发机制(一)
- (日常搬砖)windows 11 安装cython_bbox时,遇到问题‘error: Microsoft Visual C++ 14.0 or greater is required. ’解决方案
- Ubuntu 20.04 安装 php 并配置 OpenResty
- 【Flutter】Dart的方法中的可选参数、方法作为参数传递