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

Get deep insight into Node.js applications with real-time metrics, CPU profiling, and heap snapshots with N|Solid from NodeSource. Learn more.

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;




Node.js application metrics sent directly to any statsd-compliant system. Get N|Solid

Topics:

Published at DZone with permission of Alexander Beletsky, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}