Node.js 从Express堆栈中删除中间件的正确方法?
是否有一种规范的方法可以从堆栈中删除添加了Node.js 从Express堆栈中删除中间件的正确方法?,node.js,express,connect,Node.js,Express,Connect,是否有一种规范的方法可以从堆栈中删除添加了app.use的中间件?似乎是这样,但我想知道是否有一个文档化的方法我应该首先考虑。使用实际上来自Connect(不是Express),并且 所以你应该把函数从数组中拼接出来 但是,请记住,app.stack没有相关文档,也没有删除中间件的功能。您将面临未来版本的Connect可能会做出与您的代码不兼容的更改的风险。似乎没有内置的方法可以做到这一点,但您可以通过一个小技巧获得相同的结果。创建您自己的中间件数组(我们称之为dynamicMiddleware
app.use的中间件?似乎是这样,但我想知道是否有一个文档化的方法我应该首先考虑。使用实际上来自Connect(不是Express),并且
所以你应该把函数从数组中拼接出来
但是,请记住,app.stack
没有相关文档,也没有删除中间件的功能。您将面临未来版本的Connect可能会做出与您的代码不兼容的更改的风险。似乎没有内置的方法可以做到这一点,但您可以通过一个小技巧获得相同的结果。创建您自己的中间件数组(我们称之为dynamicMiddleware
),但不要将其放入express中,而是只推一个中间件,它将异步并按顺序执行dynamicMiddleware
中的所有处理程序
const async = require('async')
// Middleware
const m1 = (req, res, next) => {
// do something here
next();
}
const m2 = (req, res, next) => {
// do something here
next();
}
const m3 = (req, res, next) => {
// do something here
next();
}
let dynamicMiddleware = [m1, m2, m3]
app.use((req, res, next) => {
// execute async handlers one by one
async.eachSeries(
// array to iterate over
dynamicMiddleware,
// iteration function
(handler, callback) => {
// call handler with req, res, and callback as next
handler(req, res, callback)
},
// final callback
(err) => {
if( err ) {
// handle error as needed
} else {
// call next middleware
next()
}
}
);
})
// app is your express service
console.log(app._router.stack)
// [Layer, Layer, Layer, ...]
代码有点粗糙,因为我现在没有机会对其进行测试,但想法应该很清楚:将所有动态处理程序数组封装在一个中间件中,该中间件将在数组中循环。在向数组添加或删除处理程序时,只会调用数组中剩余的处理程序。据我所知,无法删除中间件。但是,您可以随时为“停用”中间件指定布尔标志
let middlewareA_isActivate = true;
// Your middleware code
function(req, res, next) {
if (!middlewareA_isActivate) next();
// .........
}
// Deactivate middleware
middlewareA_isActivate = false;
编辑:
在阅读了ExpressJs(4.x)代码之后,我注意到您可以通过应用程序访问中间件堆栈。_router.stack
,我猜操作就是从那里开始的。不过,我认为这一“伎俩”在future Express中可能无法奏效
P/s:未测试Express在直接操作中间件堆栈时的行为,尽管您可以使用Express动态中间件来实现这一点
像这样使用它
const express = require('express');
// import express-dynamic-middleware
const dynamicMiddleware = require('express-dynamic-middleware');
// create auth middleware
const auth = function(req, res, next) {
if (req.get('Authorization') === 'Basic') {
next();
} else {
res.status(401).end('Unauthorization');
}
};
// create dynamic middleware
const dynamic = dynamicMiddleware.create(auth);
// create express app
const app = express();
// use the dynamic middleware
app.use(dynamic.handle());
// unuse auth middleware
dynamic.unuse(auth);
如果您要从基于express构建的框架继承一些不需要的中间件,那么这是一个有用的功能
基于我之前的一些答案:在express 4.x中,可以在app.\u router.stack中找到中间件。请注意,中间件是按顺序调用的
const async = require('async')
// Middleware
const m1 = (req, res, next) => {
// do something here
next();
}
const m2 = (req, res, next) => {
// do something here
next();
}
const m3 = (req, res, next) => {
// do something here
next();
}
let dynamicMiddleware = [m1, m2, m3]
app.use((req, res, next) => {
// execute async handlers one by one
async.eachSeries(
// array to iterate over
dynamicMiddleware,
// iteration function
(handler, callback) => {
// call handler with req, res, and callback as next
handler(req, res, callback)
},
// final callback
(err) => {
if( err ) {
// handle error as needed
} else {
// call next middleware
next()
}
}
);
})
// app is your express service
console.log(app._router.stack)
// [Layer, Layer, Layer, ...]
提示:可以在各个图层中搜索要删除/移动的图层
const middlewareIndex = app._router.stack.findIndex(layer => {
// logic to id the specific middleware
});
然后,您可以使用标准阵列方法(如拼接/取消移位等)移动/移除它们
// Remove the matched middleware
app._router.stack.splice(middlewareIndex, 1);
根据以上提示,我在Express4.x上添加了以下内容。我的用例记录了Slack Bolt带来的内容,因此我可以捕获并模拟它:
// Define a handy function for re-ordering arrays
Array.prototype.move = function(from, to) {
this.splice(to, 0, this.splice(from, 1)[0]);
};
// Use the normal use mechanism, so that 'extra' stuff can be done
// For example, to log further up the order, use app.use(morgan("combined"))
app.use([my-middleware]);
// Now adjust the position of what I just added forward
const numElements = app._router.stack.length;
app._router.stack.move(numElements - 1, 1);
你可以用
console.log(“调整后堆叠”,app.\u router.Stack)
确认新订单是您想要的。(对于Slack Bolt,我必须使用app.receiver.app
,因为Bolt应用程序包装了express应用程序。)我们可以这样写
// route outside middleware
route.get("/list", (req, res)=>{
res.send("from listing route");
});
//use middleware
router.use(Middlewares.AuthMiddleware.isValidToken);
//routes inside the middleware
route.post("/create", (req, res)=>{
res.send("from create route");
});
route.delete("/delete", (req, res)=>{
res.send("from delete route");
});
因此,基本上,在将中间件注入路由之前先编写路由。或express
进行与代码不兼容的更改express
不再依赖于connect
,因此我认为这不再有效。@elmigranto这是一个过于简单的观点。您可能希望以更动态的方式使用快速路由有很多原因,在某些情况下可能需要添加/删除中间件。中间件堆栈在应用程序中。\u router.stack这不一定能解决问题。至少在我的用例中,对装载点和方法进行不同的处理是很重要的。似乎修改内部堆栈仍然是可能的,只是被移动了一点。你能更详细地说明你的用例吗。也许您可以将其封装在一个小模块中,并在不同的安装点重复使用?简要说明:下划线表示app.\u router
是专用的,即不属于公共API的一部分,因此可能会在不同版本之间更改。这可能只是作为最后的手段,但肯定是可行的。谢谢你的解释,但这并不能回答问题。