无需修改所有路由,如何在Express 5.0中获取已匹配路由列表?
Express 5.0 全局路由埋点实现方案
需求说明
无需逐个修改现有路由代码,实现全局埋点监控,让每个匹配的路由处理程序将自身的字符串模式添加到请求的数组中,后续处理程序可查看请求在应用中经过的完整路由路径。例如发起GET /bacon/delicious请求时,能输出['/bacon/:tastiness', '/:food/:tastiness']。
实现方案
通过递归遍历Express应用及所有嵌套Router的路由层(Layer),包装路由处理函数,在匹配触发时注入埋点逻辑。以下是onRouteCalled函数的具体实现:
function onRouteCalled(app, callback) { // 递归处理Router的所有路由层 function processRouter(router) { router.stack.forEach(layer => { // 处理普通路由(如app.get、router.post定义的路由) if (layer.route) { const originalHandle = layer.handle; layer.handle = function(req, res, next) { callback(req, layer.route.path); originalHandle.call(this, req, res, next); }; } // 处理嵌套Router实例 else if (layer.handle && layer.handle.name === 'router') { processRouter(layer.handle); } // 处理use方式定义的路由(如app.use('/path', ...)) else if (layer.path) { const originalHandle = layer.handle; layer.handle = function(req, res, next) { callback(req, layer.path); originalHandle.call(this, req, res, next); }; } }); } processRouter(app); }
使用示例
将上述函数与业务代码结合,即可实现路由路径的收集:
const express = require('express'); const { Router } = express; const app = express(); onRouteCalled(app, (req, route) => { req.myMatchedRoutes ??= []; req.myMatchedRoutes.push(route); }); app.use(function logPath(req, res, next) { res.on('close', () => { console.log(req.myMatchedRoutes); }); next(); }); const router = Router(); router.use('/bacon/:tastiness', (req, res, next) => next()); router.use('/:food/:tastiness', (req, res, next) => { res.sendStatus(204); }); app.use(router); app.listen(3000, () => { console.log('Server running on port 3000'); });
当发起GET http://localhost:3000/bacon/delicious请求后,控制台会输出:
['/bacon/:tastiness', '/:food/:tastiness']
原理说明
- Express的路由系统基于
Layer对象,每个路由(包括use定义的中间件路由)对应一个Layer实例 - 该方案通过包装Layer的
handle方法,在原处理逻辑执行前触发埋点回调,收集当前匹配的路由模式 - 递归处理嵌套Router,确保所有层级的路由都能被监控到
内容的提问来源于stack exchange,提问作者Adam A
相关产品推荐
相关产品推荐

