为何Express Router中间件会匹配到未绑定到该路由实例的路径
原因解释
你遇到的现象是Express的中间件匹配规则和注册顺序共同导致的:
- Express的中间件、路由完全按照注册顺序依次匹配执行,你代码里
app.use(router)的注册顺序早于app.get('/noRouter'),所有请求都会优先进入router的处理流程。 - 你调用
app.use(router)时没有指定挂载路径前缀,相当于这个router默认匹配所有路径的请求,不管访问什么路径都会先进入router内部处理。 - router上挂载的无路径限制中间件
router.use(...)会对所有进入router的请求生效,执行完打印逻辑调用next()后,router发现当前路径没有匹配到自身注册的路由,就会跳出router,继续匹配app栈后续的app.get('/noRouter'),所以才会出现访问/noRouter也打印日志的情况。
实现仅作用于自身路由的Router
如果你的路由没有公共前缀,又想让中间件只作用于指定Router下的路由,可以用两种常见方案:
方案1:调整注册顺序
把所有不需要用到该Router中间件的路由,全部注册在app.use(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() }) // 先注册不需要Router中间件的路由 app.get('/noRouter', (req, res) => { res.send("ok") }) // 再挂载Router,只有前面没匹配到的请求才会进入Router app.use(router) router.get('/router', (req, res) => { res.send("ok") }) app.listen(port, () => { console.log(`Listening at http://localhost:${port}`) })
方案2:拆分公共中间件单独注入
把通用中间件拆成独立函数,给Router下的每个路由单独注入,避免全局挂载到Router上:
const commonMiddleware = (req, _res, next) => { console.log("router called") next() } // Router不需要再全局挂载中间件 const router = express.Router(); // 每个需要用到中间件的路由单独加参数即可 router.get('/router', commonMiddleware, (req, res) => { res.send("ok") }) router.get('/other/path/without/common/prefix', commonMiddleware, (req, res) => { res.send("ok") }) app.use(router)
内容的提问来源于stack exchange,提问作者Peter V. Mørch
相关产品推荐
相关产品推荐

