Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Catch Errors in Express.js Application

DZone's Guide to

Catch Errors in Express.js Application

· Web Dev Zone ·
Free Resource

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

This is a small follow up for my previous post, using the same technique, not for authorization, but rather for error handling.

Let’s go back to the problem. I want to handle all errors in my application. Instead of res.send() or res.json(), I want to have a middleware that handles everything by itself. It can be flexible, so I can put any kind of logic there, like logging, etc.

It’s very easy to archive with patch the middleware method.

Just like in the previous case, app.use() won’t work here. First, it would apply to every request. Second, error handling middleware has to be placed last and app.use() won’t guarantee that.

Follow the Style

To get the benefits of common error handling/logging code, you have to follow a particular style. It’s very simple though.

Your last endpoint (middleware) function has to always receive the next() callback parameter. All logs have to pass as the first argument to that function. You should not send errors directly as res.send(500, 'Error').

app.get('/api/users/:id', function (req, res, next) {
  db.users.find({id: req.params.id}, function (err, user) {
      if (err) {
          return next({message: 'failed to query db', status: 500});
      }

      if (!user) {
          return next({message: 'user not found', status: 404});
      }

      res.json(user);
  });
});

Please note that it receives the first argument and the function is only called when we call next() with the first parameter.

Error Handler Middleware

Let’s define the function. Since HTTP API’s are JSON based, it would just return the JSON response and status.

function logErrors(err, req, res, next) {
  req.unhandledError = err;

  var message = err.message;
  var error = err.error || err;
  var status = err.status || 500;

  res.json({message: message, error: error}, status);
};

Apply the Patch

Again, right after all routes are already defined, let’s call applyErrorLogging().

// ...

require('./source/api')(app);
require('./source/router')(app);

applyAuthentication(app, ['/api']);
applyErrorLogging(app);                 // apply error handling here

// ...

And the applyErrorLogging() function,

var middleware = require('../middleware');

function applyErrorLogging(app) {
  for (var verb in app.routes) {
      var routes = app.routes[verb];
      routes.forEach(patchRoute);
  }

  function patchRoute (route) {
      route.callbacks.push(middleware.errors.logErrors);
  }
}

module.exports = applyErrorLogging;




Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Topics:

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}