【问题标题】:Express router middleware gets called on unexpected routesExpress 路由器中间件在意外路由上被调用
【发布时间】:2021-09-12 17:41:28
【问题描述】:

使用 express,我有多个需要中间件的路由。它们不在任何常见的/url/path下。

Router-level middleware 说:

路由器级中间件的工作方式与应用级中间件相同,只是它绑定到 express.Router() 的实例

当我读到它时,这意味着中间件仅适用于路由器实例的路由。但似乎并非如此。

在以下示例中,我希望仅为http://localhost:10000/router 记录“路由器调用”。

但它也被记录为http://localhost:10000/noRouter,我不明白。为什么router 实例的中间件used 会被直接添加到app 的路由调用?是否可以创建一个Router,以便只有绑定到该Router 的路由才能应用中间件?

const express = require('express')

const app = express()
const port = 10000

const router = express.Router();
router.use((req, _res, next) => {
    console.log("router called")
    next()
})

app.use(router)

router.get('/router', (req, res) => {
    res.send("ok")
})

app.get('/noRouter', (req, res) => {
    res.send("ok")
})

app.listen(port, () => {
    console.log(`Listening at http://localhost:${port}`)
})

P.S.:我没有被卡住,而是使用不同的方法让它工作。我只是想了解为什么这不起作用...

【问题讨论】:

  • 因为中间件的first,不限于特定的路由,并且调用next - 这就是应该发生的
  • @jonrsharpe:嗯。我平时不厚,但我还是不明白。您已将first 以斜体字表示,但first 仅在我理解的不相关上下文中出现在Router-level middleware 中一次。我仍然不明白我的中间件函数“绑定到 express.Router() 的实例”是什么意思。但是感谢您尝试启发我! :-)

标签: express routes


【解决方案1】:

路由器只是插入到请求处理程序链中,并按顺序搜索/执行。

因为你这样做:

app.use(router)

您专门将所有请求发送到您的路由器。因此,所有请求都将通过该路由器中的各种处理程序来寻找与传入路径匹配的处理程序。这将包括您的 router.use() 中间件,它匹配所有路径,因此它将针对发送到您的路由器的每个 URL 执行。在执行任何中间件之前,路由器中没有首先检查路由器中的某些路由是否匹配的逻辑。在这方面,路由器就像app 对象一样工作,并按照遇到它们的顺序执行中间件。因此,您的中间件不被执行的唯一方法是请求根本不会到达路由器。

如果您希望中间件仅适用于路由器中的路由,那么您有两个选择:

将路由器放在公共路径前缀上,例如:

app.use("/somerouterprefix", router);

然后,只有路由到您的路由器的 URL 才能运行路由器中的中间件。当然,这只会为以该前缀开头的路由执行中间件,但它也会为以该前缀开头的路由执行中间件,但路由器中甚至没有匹配的路由处理程序。请记住,我之前说过,发送到路由器的所有内容都会导致您的中间件执行。

或者,其次,将中间件放在路由器中的每个单独的处理程序上,这样它只会在它与路由器上的某些路由匹配时才会被执行,例如:

const router = express.Router();

// give the middleware a function name so you can 
//   use it in specific route definitions
function myMiddleware((req, _res, next) => {
    console.log("router called")
    next()
});

// specify the middleware in your route definition
router.get('/router', myMiddleware, (req, res) => {
    res.send("ok")
});

【讨论】:

  • 谢谢,我最终使用了解决方案 #2,因为正如我所说的“它们不在任何常见的 /url/path 下”。鉴于这种解释,我认为文档中的这句话具有误导性:“路由器级中间件的工作方式与应用级中间件相同,只是它绑定到 express.Router() 的实例”。
  • @PeterV.Mørch - 文档中的特定短语在技术上是正确的,但并不能说明全部情况。如果传入请求通过您注册路由器的中间件发送到路由器,则该路由器中的router.use() 就像app.use() 一样工作。不同之处在于路由器是否以仅向路由器发送一些请求的方式注册(如我回答中的第一个示例)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2017-03-08
  • 2016-04-11
  • 1970-01-01
相关资源
最近更新 更多