简体   繁体   中英

node.js and express - using multiple middlewares vs. callbacks - what's the best practice?

I have a question regarding building a HTTP service with express that requires to run some pre-checks before running the actual function (and if one of the pre-checks fails, not to run the function).

For example, first check if the request is authorized, then check the permissions, and only if both pass run the actual function. I can think of two ways to do that with express, either by writing both authorization and permissions as middlewares, or using callbacks.

Which approach is the best practice for express? Using middlewares looks more elegant, but is it better? What are the pros and cons for both solutions?

Using callbacks will look like this:

router.get( '/myResource',, function(req, res){ 
  autorizationCB(function(err, data){
    if (err) {
      return res.status(401).json({message: err.message});
    } 
    permissionsCB(function (err, data) {
      if (err) {
        return res.status(403).json({message: err.message});
      }
      // actual resource code...
    });
  });
});

function authorizationCB(callback) {
  // check authorization
  ...
  ...
  if (authorized) {
    return callback(null, data);
  } else { 
    return callback({message: 'some authorization error msg'});
  }
}
function permissionsCB(callback) {
  // check permissions
  ...
  ...
  if (permitted) {
    return callback(null, data);
  } else { 
    return callback({message: 'some permissions error msg'});
  }
}

Middlewares would look like this:

router.get('/myResource', 
   authurizationMW, 
   permissionsMw, 
   function(req, res){ 
      // actual resource code...
   });

function authorizationMW(req, res, next) {
  //check if authorized
  ...
  ...
  if (authorized) {
    next();
  } else {
    res.status(401).json({message: 'not authorized'});
  }
}
function permissionsMW(req, res, next) {
  //check if permitted
  ...
  ...
  if (permitted) {
    next();
  } else {
    res.status(403).json({message: 'no permissions'});
  }
}

Middlewares are more reusable. I would actually do something like this for example on how to better reuse:

var secureRouter = ...
secureRouter.use(authorizationMW);
secureRouter.use(permissionsMW);

var appRouter = ....
secureRouter.use(appRouter);

//all routes are protected....
appRouter.get('/myResource', 
   function(req, res){ 
      // actual resource code...
   });
);
appRouter.get('/myResource2', 
   function(req, res){ 
      // actual resource code...
   });
);
//.. so on....

Actually middlewares are exactly for these purposes, and using them there is no need to add required middlewares to every single route, you can add them to the router and they will only get called for routes under the router:

app.use('/user', authorizationMW, permissionsMW, require('./routes/user'));

I haven't seen your mentioned callback strategy anywhere. Downsides, your code won't be readable, there are many nested levels and you must repeat all of these codes to each route on the router!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM