Proper way to remove middleware from the Express stack?

后端 未结 7 2068
时光说笑
时光说笑 2020-12-18 18:41

Is there a canonical way to remove middleware added with app.use from the stack? It seems that it should be possible to just modify the app.stack array directl

相关标签:
7条回答
  • 2020-12-18 19:10

    No way of removing a middleware as far as I know. however, you can assign a boolean flag to 'deactivate' a middleware at anytime you want.

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

    EDIT :
    After reading through ExpressJs (4.x) code, I notice that you can access the middlewares stack via app._router.stack, manipulation goes from there I guess. Still, I think this 'trick' might not be able to work in future Express
    P/s: Not tested how Express behaves when manipulate the middlewares stack directly though

    0 讨论(0)
  • 2020-12-18 19:12

    Following from the hints above, I've add success with the following on express 4.x. My use case was logging what was coming in with Slack Bolt, so I could capture and then mock it:

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

    You can use console.log("Stack after adjustment", app._router.stack) to confirm the new order is what you want. (For Slack Bolt, I had to use app.receiver.app because the Bolt app wraps the express app.)

    0 讨论(0)
  • 2020-12-18 19:16

    There seems to be no built in way to do that, but you can manage to get the same result with a small trick. Create your own array of middleware (let's call it dynamicMiddleware) but don't push that into express, instead push just 1 middleware that will execute all the handlers in dynamicMiddleware asynchronously and in order.

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

    The code is a bit rough as I don't have a chance to test it right now, but the idea should be clear: wrap all dynamic handlers array in 1 middleware, that will loop through the array. And as you add or remove handlers to the array, only the ones left in the array will be called.

    0 讨论(0)
  • 2020-12-18 19:20

    We can write like this.

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

    So basically, write routes before injecting middleware into your route.

    0 讨论(0)
  • 2020-12-18 19:30

    use actually comes from Connect (not Express), and all it really does is push the middleware function onto the app's stack.

    So you should be just fine splicing the function out of the array.

    However, keep in mind there is no documentation around app.stack nor is there a function to remove middleware. You run the risk of a future version of Connect making changes incompatible with your code.

    0 讨论(0)
  • 2020-12-18 19:32

    This is a useful functionality if you are inheriting some unwanted middleware from a framework built on express.

    Building on some of the answers that came before me: In express 4.x the middleware can be found in app._router.stack. Note that the middleware are invoked in order.

    // app is your express service
    
    console.log(app._router.stack)
    // [Layer, Layer, Layer, ...]
    

    Tip: You can search the individual layers for the one you want to remove/move

    const middlewareIndex = app._router.stack.findIndex(layer => {
     // logic to id the specific middleware
    });
    

    Then you can just move/remove them with standard array methods like splice/unshift/etc

    // Remove the matched middleware
    app._router.stack.splice(middlewareIndex, 1);
    
    0 讨论(0)
提交回复
热议问题