如何在Express中获取请求匹配的原始URL路由模式?
获取Express匹配请求的原始路由模式
要拿到像/api/user/:userId这种带参数占位符的原始路由模式,Express没有直接提供全局可用的属性,但可以通过以下几种方法实现:
方法一:使用req.route.path(推荐,适用于路由级中间件)
req.route.path会返回当前请求匹配到的路由模式,但注意这个属性只有在路由处理函数或挂载在具体路由上的中间件中才能获取到,全局中间件(app.use直接挂载的)如果在路由定义之前执行,req.route还未初始化,会返回undefined。
示例代码:
// 定义权限校验中间件 const checkPermission = (req, res, next) => { const routePattern = req.route.path; console.log('匹配的路由模式:', routePattern); // 输出 /api/user/:userId // 结合数据库中的权限配置进行校验 // if (用户权限包含routePattern) 放行,否则拒绝 next(); }; // 将中间件挂载到具体路由上 app.get('/api/user/:userId', checkPermission, (req, res) => { res.send('用户详情'); }); // 嵌套路由场景同样适用 const userRouter = express.Router(); userRouter.get('/:userId', checkPermission, (req, res) => { res.send('嵌套路由下的用户详情'); }); app.use('/api/user', userRouter); // 此时req.route.path会返回 /:userId,结合req.baseUrl可拼接成完整路由模式:/api/user/:userId
如果需要完整的路由路径(包括嵌套路由的前缀),可以结合req.baseUrl:
const fullRoutePattern = `${req.baseUrl}${req.route.path}`; console.log(fullRoutePattern); // 输出 /api/user/:userId
方法二:全局中间件中匹配路由模式(适用于全局权限校验)
如果必须在全局中间件中获取路由模式,可以手动遍历Express的路由栈,收集所有路由的模式和匹配正则,再在中间件中匹配当前请求。
第一步:收集所有路由
function collectAllRoutes(router, parentPath = '') { const routes = []; router.stack.forEach(layer => { // 处理单个路由规则 if (layer.route) { const fullPath = parentPath + layer.route.path; routes.push({ path: fullPath, regex: layer.regexp, methods: layer.route.methods }); } // 处理嵌套的Router else if (layer.name === 'router') { const childRoutes = collectAllRoutes(layer.handle, parentPath + layer.path); routes.push(...childRoutes); } }); return routes; } // 收集app中的所有路由(需在所有路由定义后执行) const allAppRoutes = collectAllRoutes(app);
第二步:全局中间件中匹配
app.use((req, res, next) => { const currentMethod = req.method.toLowerCase(); // 按路由定义顺序匹配(Express路由是按顺序匹配的,确保拿到第一个匹配的路由) const matchedRoute = allAppRoutes.find(route => { return route.regex.test(req.originalUrl) && route.methods[currentMethod]; }); if (matchedRoute) { console.log('匹配的路由模式:', matchedRoute.path); // 在这里进行权限校验逻辑 } next(); });
注意事项
- 确保
collectAllRoutes在所有路由定义完成后调用,否则会遗漏路由。 - 对于使用正则定义的路由(如
/api/user/:id(\\d+)),收集到的path会保留正则部分,需要根据实际权限存储格式调整。
内容的提问来源于stack exchange,提问作者Gabriel Loch
相关产品推荐
相关产品推荐

