'exit from express middleware with specific http status
Hopefully this is a simple one, but I have some custom middleware which I want to return a 404 or 401 etc to the user and stop the propagation of other handlers etc.
I was expecting I could do something like:
function SomeMiddleware(req, res, next) {
if(user.notRealOrSomething)
{ throw new HttpException(401, "Tough luck buddy"); }
return next();
}
However cannot find any specific info about how is best to do this.
Solution 1:[1]
You are suppose to pass errors to the next()
function.
function SomeMiddleware(req, res, next) {
if(user.notRealOrSomething) {
return next(throw new HttpException(401, "Tough luck buddy"));
}
next();
}
Any argument you pass to next
will be considered an error except 'route'
which will skip to the next route.
When next is called with an error the error middleware will be execute.
function (err, req, res, next) {
// err === your HttpException
}
Express.js will treat any middleware with 4 arguments as error middleware.
Error-handling middleware are defined just like regular middleware, however must be defined with an arity of 4, that is the signature (err, req, res, next):
All of this is pretty well documented at: http://expressjs.com/guide/error-handling.html
Solution 2:[2]
Nothing prevents you from using the response object:
res.send(401, "Tough luck buddy");
next('invalid user');
Solution 3:[3]
The code as written in the answer should work just fine, since the code is synchronous - that is, it's not async
and it doesn't hand next()
off to a callback anywhere. Per the Express.js docs (emphasis mine):
Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then Express will catch and process it.
So in synchronous middlewares and handlers, just throw the error, Express will catch it and pass it to the error middleware.
For asynchronous middlewares, you need to pass the error object to the next()
function without throwing it. The example from the docs applies just as well to middlewares as it does to route handlers (which are in fact also middleware), to adapt it to your example:
function SomeMiddleware(req, res, next) {
user.checkRealOrSomethingAsync(isReal => {
if(!isReal) {
// Note: Pass the exception, do not throw it!
next(new HttpException(401, "Tough luck buddy"))
}
next()
})
}
Note that, as per the Express docs, this means you must catch any errors thrown in async middlewares or routes and pass them into next()
.
However! Starting in Express 5, you don't need to catch errors thrown within async
methods, the error will be propagated as normal without you doing anything. express-async-errors package will patch Express.js 4 to work similarly. Note this only applies to errors at the "top level" of the async function - if you're mixing async and callbacks, you'll still have to catch errors inside the callbacks.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Patrick Fowler |
Solution 2 | kolypto |
Solution 3 |