Reputation: 731
According to the documentation, any nodejs express middleware function can be replaced by App or Router instances:
Since router and app implement the middleware interface, you can use them as you would any other middleware function.
This is some generic error handling I use:
express()
.use('/test', new TestRouter())
.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send(err.message);
})
.listen(PORT);
I tried to replace my error handling with an error-handling Router, but now the callback is never executed and express uses it's default error handling.
const handler = new express.Router();
handler.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send(err.message);
});
express()
.use('/test', new TestRouter())
.use(handler)
.listen(PORT);
Why is this not working as expected and how could I solve it?
Upvotes: 5
Views: 2920
Reputation: 82096
Error handlers need to be configured as the last calls to use
, as per the docs
You define error-handling middleware last, after other app.use() and routes calls;
I would say "routes" also buckets Routers therefore what you are trying to do doesn't look like it's supported.
Just digging further into this, I believe the issue is down to the fact Routers have separate Layer stacks. Express behind the scenes is effectively just a Router
(we see here where this is setup, and then further down where the middleware is delegated on to the Router). Internally, middleware functions are represented as "Layers" (as seen here) and looking at the constructor, we can see Routers have their own stack.
So consider the following example:
express()
.use(new RouterA())
.use(new RouterB())
.use((err, req, res, next) => {
...
})
.listen(PORT);
Which, by looking at the source, can be viewed as:
express()
.use((req, res, next) => {
router.handle(req, res, next);
})
.use((req, res, next) => {
router.handle(req, res, next);
})
.use((err, req, res, next) => {
...
});
Therefore, if an error is thrown in RouterA
, the Router would firstly check its own middleware stack for a matching error Layer (i.e. a (err, req, res, next)
function) and execute that, it would then bubble up to the app level and perform the same action.
So given your example, if you consider the translated code, this explains why it won't catch your error handler in the second Router - a Router signature does not match that of an error handler therefore it would be skipped.
Upvotes: 4