【发布时间】:2023-03-26 22:15:01
【问题描述】:
我的路线映射为:
app.get('/health/*', function(req, res){
res.send('1');
});
如何在运行时将此路由删除/重新映射到空处理程序?
【问题讨论】:
我的路线映射为:
app.get('/health/*', function(req, res){
res.send('1');
});
如何在运行时将此路由删除/重新映射到空处理程序?
【问题讨论】:
您可以查看 Express route middleware 并可能进行重定向。
【讨论】:
可以在服务器运行时移除挂载的处理程序(通过 app.use 添加),尽管没有 API 可以执行此操作,因此不建议这样做。
/* Monkey patch express to support removal of routes */
require('express').HTTPServer.prototype.unmount = function (route) {
for (var i = 0, len = this.stack.length; i < len; ++i) {
if (this.stack[i].route == route) {
this.stack.splice(i, 1);
return true;
};
}
return false;
}
这是我需要的东西,所以很遗憾没有合适的 api,但 express 只是在模仿 connect 在这里所做的事情。
【讨论】:
app.get$ = function(route, callback){
var k, new_map;
// delete unwanted routes
for (k in app._router.map.get) {
if (app._router.map.get[k].path + "" === route + "") {
delete app._router.map.get[k];
}
}
// remove undefined elements
new_map = [];
for (k in app._router.map.get) {
if (typeof app._router.map.get[k] !== 'undefined') {
new_map.push(app._router.map.get[k]);
}
}
app._router.map.get = new_map;
// register route
app.get(route, callback);
};
app.get$(/awesome/, fn1);
app.get$(/awesome/, fn2);
然后当你去http://...awesomefn2时会被调用:)
编辑:修复代码
Edit2:再次修复...
Edit3:也许更简单的解决方案是在某个时候清除路由并重新填充它们:
// remove routes
delete app._router.map.get;
app._router.map.get = [];
// repopulate
app.get(/path/, function(req,res)
{
...
});
【讨论】:
Express(至少从 3.0.5 开始)将其所有路线保留在 app.routes 中。来自documentation:
app.routes 对象包含由关联的 HTTP 动词映射定义的所有路由。此对象可用于自省功能,例如 Express 在内部不仅将其用于路由,而且还提供默认的 OPTIONS 行为,除非使用 app.options()。您的应用程序或框架也可以通过简单地从该对象中删除路由来删除路由。
您的app.routes 应该与此类似:
{ get:
[ { path: '/health/*',
method: 'get',
callbacks: [Object],
keys: []}]
}
因此,您应该能够循环访问app.routes.get,直到找到您要查找的内容,然后将其删除。
【讨论】:
这会删除 app.use 中间件和/或 app.VERB (get/post) 路由。在 express@4.9.5 上测试
var routes = app._router.stack;
routes.forEach(removeMiddlewares);
function removeMiddlewares(route, i, routes) {
switch (route.handle.name) {
case 'yourMiddlewareFunctionName':
case 'yourRouteFunctionName':
routes.splice(i, 1);
}
if (route.route)
route.route.stack.forEach(removeMiddlewares);
}
请注意,它要求中间件/路由函数具有名称:
app.use(function yourMiddlewareFunctionName(req, res, next) {
... ^ named function
});
如果函数是匿名的,它将不起作用:
app.get('/path', function(req, res, next) {
... ^ anonymous function, won't work
});
【讨论】:
route.path 包含路径名 - 如果你想通过路径删除匿名路由,你可以打开它。
route.path 在我的情况下未定义,但 route.route.path 具有正确的值
如上所述,新的 Express API 似乎不支持这一点。
真的有必要完全删除映射吗?如果您只需要停止为路由提供服务,则可以轻松地开始从处理程序返回一些错误。
唯一(非常奇怪)的情况是,如果一直添加动态路由,并且您希望完全摆脱旧路由以避免累积太多...
如果你想重新映射它(要么做其他事情,要么将它映射到总是返回错误的东西),你总是可以添加另一个级别的间接:
var healthHandler = function(req, res, next) {
// do something
};
app.get('/health/*', function(req, res, next) {
healthHandler(req, res, next);
});
// later somewhere:
healthHandler = function(req, res, next) {
// do something else
};
在我看来,这比在 Express 中处理一些未记录的内部结构更好/更安全。
【讨论】:
Host 字段等标头信息来确定这些路由的范围。我可能只会将所有请求路由到同一个处理程序,然后在 Express 路由 API 之外执行我自己的自定义路由。
上述方法要求您为路线指定一个命名函数。我也想这样做,但没有为路由命名的函数,所以我编写了一个 npm 模块,可以通过指定路由路径来删除路由。
给你:
【讨论】:
没有官方方法,但您可以使用 stack 来做到这一点。
function DeleteUserRouter(appName){
router.stack = router.stack.filter((route)=>{
if(route.route.path == `/${appName}`){
return false;
}
return true;
});
}
appName 是路径名。
过滤router为express.Router的router.route.stack中的方法 或者您可以对应用程序执行相同的操作,但使用 app._router.stack。
注意:4.0以下使用-app.router.stack。
【讨论】: