Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express middleware error handler

Following a generated template for express. In the app.js there is a following snippet

app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

Per my understanding, the middleware will run in order from app.use('/users', users) to 404 handler to error handler. My question is how will it be possible to reach error handler and execute this line res.status(err.status || 500); ? Wont every failed request be passed through 404 handler first and therefor getting the status code of 404? Please let me know if I am missing something! Thank you

like image 540
Zanko Avatar asked Aug 20 '17 23:08

Zanko


2 Answers

No, it won't. If you look at these event handlers declarations you'll see that error handler for unhandled error, has an additional err parameter:

app.use(function(req, res, next) {
app.use(function(err, req, res, next) {

Error-handling middleware always takes four arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the next object, you must specify it to maintain the signature. Otherwise, the next object will be interpreted as regular middleware and will fail to handle errors. For details about error-handling middleware.

So, when the route is not found, the last declared middleware is calling, it's 404 error handler.

But when you call next with error: next(err) or your code throws an error, the last error handler is calling.

like image 141
alexmac Avatar answered Sep 26 '22 14:09

alexmac


System error should be handled before 404

app.use('/users', users);

// error handler
app.use(function(err, req, res, next) {
  // No routes handled the request and no system error, that means 404 issue.
  // Forward to next middleware to handle it.
  if (!err) return next();

  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

// catch 404. 404 should be consider as a default behavior, not a system error.
app.use(function(req, res, next) {
  res.status(404);
  res.render('Not Found');
});
like image 38
haotang Avatar answered Sep 23 '22 14:09

haotang