I'm learning express.js / node.js and have a good but not excellent understanding of the javascript prototype model. Hence, I'm a bit confused on the way middleware can be stacked in express.js's routing mechanisms.
Say we have this code
function andRestrictTo(role) {
return function(req, res, next) {
req.authenticatedUser.role == role
? next() : next(new Error('Unauthorized'));
}
}
app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
res.send('Deleted user ' + req.user.name);
});
Since andRestrictTo(role) returns a middleware, it get's executed in the routing chain - I got that. However:
Where does the req, res, next parameters come from in the returned function? I guess that the "chain" is somehow queuing it and assings the parameters, but this is a bit too vague for a deeper understanding ...
What is happening with the Error that is raised as next's parameter? Does an error simply break the middleware chain?
If I would want to package the restriction mechanism to a separate file / module (like a security framework), how would that be done?
It would be cool if someone could point out the basic idea :)
1) req
and res
come from the very source of Express JS, i.e. Node.JS http.createServer
handler (both variables are modified a bit before actually hitting Express' handler). At that point Express holds the array of all routes and applies req
, res
and next
function to each route. next
function knows at which middleware we are at the moment (due to some scoping tricks) and calling it like this: next()
takes you to the next handler.
2) When the error is raised (actually not raised, but passed to), the next
function takes you to the error handler, which you can define using error
method of app
, for example (taken from Express documentation):
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
});
Raising error
breakes a chain of middlewares and takes you to the chain of error handlers (as you can see, you use next
in error handlers as well).
3) Not difficult at all:
security.js
module.exports = function(req, res, next) {
console.log('Security middleware!');
next();
}
app.js
app.get('/', require('./security'), ...);