NodeJS 从Express堆栈中删除中间件的正确方法?

kse8i1jr  于 2023-05-22  发布在  Node.js
关注(0)|答案(7)|浏览(174)

是否有一种规范的方法可以从堆栈中删除添加了app.use的中间件?
它似乎是should be possible to just modify the app.stack array directly,但我想知道是否有一个文档化的方法,我应该首先考虑。

iecba09b

iecba09b1#

use实际上来自Connect(而不是Express),它真正做的就是将中间件功能推送到应用程序的stack上。
所以你应该很好地将函数从数组中拼接出来。
但是,请记住,没有关于app.stack的文档,也没有删除中间件的函数。您可能会面临未来版本的Connect做出与您的代码不兼容的更改的风险。

c7rzv4ha

c7rzv4ha2#

如果您要从基于express构建的框架继承一些不需要的中间件,这是一个有用的功能。
基于我之前的一些答案:在express 4.x中,中间件可以在app. router. stack中找到。请注意,中间件是按顺序调用的。

// 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
});

然后你就可以用标准的数组方法来移动/移除它们,比如splice/unshift/etc

// Remove the matched middleware
app._router.stack.splice(middlewareIndex, 1);
eoigrqb6

eoigrqb63#

似乎没有内置的方法来做到这一点,但你可以设法得到同样的结果与一个小技巧。创建您自己的中间件阵列(我们称之为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()
            }
        }
    );
})

代码有点粗糙,因为我现在没有机会测试它,但想法应该很清楚:将所有动态处理程序数组 Package 在1个中间件中,该中间件将循环遍历该数组。当您向数组中添加或删除处理程序时,将只调用数组中剩余的处理程序。

ff29svar

ff29svar4#

您可以使用express-dynamic-middleware来实现这一点。
https://github.com/lanbomo/express-dynamic-middleware
像这样使用它

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);
uxh89sit

uxh89sit5#

据我所知,没有办法删除中间件。但是,您可以指定一个布尔标志,以便在任何需要时候“停用”中间件。

let middlewareA_isActivate = true;
// Your middleware code
function(req, res, next) {
   if (!middlewareA_isActivate) next();
   // .........
}
// Deactivate middleware
middlewareA_isActivate = false;

编辑:

在阅读了ExpressJs(4.x)代码之后,我注意到您可以通过app._router.stack访问中间件堆栈,我猜操作就是从那里开始的。不过,我认为这种'伎俩'可能无法在未来的快车工作
P/s:没有测试Express在直接操作中间件堆栈时的行为

ztyzrc3y

ztyzrc3y6#

根据上面的提示,我在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("Stack after adjustment", app._router.stack)来确认新订单是您想要的。(对于Slack Bolt,我不得不使用app.receiver.app,因为Bolt应用程序 Package 了express应用程序。

yqkkidmi

yqkkidmi7#

我们可以这样写。

// 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");  
});

因此,基本上,在将中间件注入路由之前编写路由。

相关问题