Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a expressjs middleware that accepts parameters

People also ask

How do you pass arguments to middleware?

To achieve this, you can use a simple but efficient pattern: wrap your actual middleware function with a second one that receives the desired parameters, like so. Then, simply pass the desired parameter to the middleware wrapper function when passing to the Express routes.

How many parameters you should pass in the middleware function?

Error-handling middleware always takes four arguments. You must provide four arguments to identify it as an error-handling middleware function.

Does Express support middleware?

Middleware functions are functions that have access to the request object ( req ), the response object ( res ), and the next function in the application's request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.

How do I pass middleware in node JS?

If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.


function HasRole(role) {
  return function(req, res, next) {
    if (role !== req.user.role) res.redirect(...);
    else next();
  }
}

I also want to make sure that I don't make multiple copies of the same function:

function HasRole(role) {
  return HasRole[role] || (HasRole[role] = function(req, res, next) {
    if (role !== req.user.role) res.redirect(...);
    else next();
  })
}

app.get('/hasToBeAdmin', (req, res, next) => {
  hasRole(req, res, next, 'admin');
}, (req,res) => { 
    // regular route 
});

const hasRole = (req, res, next, role) => {
   if(role != user.role){
      res.redirect('/NotInRole');
   }
   next();
};

Alternatively if you do not have too many cases or if role is NOT a string:

function HasRole(role) {
  return function (req, res, next) {
    if (role !== req.user.role) res.redirect(/* ... */);
    else next();
  }
}

var middlware_hasRoleAdmin = HasRole('admin'); // define router only once

app.get('/hasToBeAdmin', middlware_hasRoleAdmin, function (req, res) {

})

I use this solution. I recieve a jwt token in body req, and get role information from there

//roleMiddleware.js

const checkRole = role => {
    
    return (req, res, next) => {
        if (req.role == role) {
            console.log(`${role} role granted`)
            next()
        } else {
            res.status(401).send({ result: 'error', message: `No ${role} permission granted` })
        }
    }
}

module.exports = { checkRole }

So first I use auth middleware to know if is a valid user, and then the role middleware to know if user have access to the api route

// router.js

router.post('/v1/something-protected', requireAuth, checkRole('commercial'), (req, res) => {
    // do what you want...
})

I hope to be useful


If you have various permissions levels you could structure them like this:

const LEVELS = Object.freeze({
  basic: 1,
  pro: 2,
  admin: 3
});

/**
 *  Check if user has the required permission level
 */
module.exports = (role) => {
  return (req, res, next) => {
    if (LEVELS[req.user.role] < LEVELS[role]) return res.status(401).end();
    return next();
  }
}

Since we are in 2021 why not using an ES6 syntax?... Using NodeJS v14.16.1 the example below works like a charm :-)

With express routers

const someFunc = ({ option1, option2 }) =>
 router.get("/", (req, res, next) => {
    
 // code
    
 next();
});

module.exports = someFunc;

or

const someFunc = ({ option1, option2 }) =>
     (req, res, next) => {
        
     // code
        
     next();
    };
    
 module.exports = someFunc;

... Then call it like:

const someFunc = require('./middlewares/someFunc.js');
app.use(someFunc({option1: 'test', option2: false ));