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'), ...);
1) Express's (actually Connect's) routing code takes an HTTP request and begins passing it along to all the middleware functions, calling each of them with the req
and res
that came along with the request, and adding a next
that invokes the part of the routing code that passes control along to the next middleware function in the chain.
2) No error has been raised (only a throw
statement can actually raise an error). The routing code recognizes that a middleware function has returned an Error
object, and deals with that appropriately.
3) You'd just put it into a module that exports andRestrict
(if it were the only externally-usable function in the module, you'd set exports=andRestrict
and then invoke it with require('mymodule')
); otherwise you'd set exports.andRestrict=<body of your function>
and invoke it in two steps: mymodule=require('mymodule')
early on, and mymodule.andRestrict
later on (e.g. when passing it as middleware)).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With