An elegant solution for handling errors in Express
Express is a microframework that according to 2018 Node.js User Survey Report is used by 4 in 5 back-end and full-stack node.js developers. Thanks to its simplicity, the always-growing range of available middleware, and active community the express userbase is still growing.
Arguably, the simplicity of Express is its most significant advantage but comes with a cost of bare-bones API for handling requests and leaves the rest to the developer. In general, it’s fantastic! We’re developers, and we love to roll out the solutions that we tailor to meet our requirements.
The two everyday tasks for each RESTful application is handling errors and payload validation. I like to keep my controllers lean, so for me, middleware is the way to deal with framework-ish features like these two.
Code is available on GitHub: MichalZalecki/express-errors-handling.
Hapi.js is another framework for building web services in Node.js. Hapi.js extracts input validation out of controllers into the intermediate layer between router and route handlers. Hapi is very modular and its schema validation component is a separate library called Joi. We are going to use Joi with our Express application through the Celebrate, an Express middleware for Joi.
Using Celebrate with Joi is a quick and easy way to validate your schema and respond with a well-formatted error message. It also helps to keep your controllers lean, so you can assume that data from the request payload is well formatted.
That’s how the sample error response may look like:
Some errors are accidental like database constraint violation, lost connection, third-party service timeout, and some are expected under precisely defined conditions like token expiration, incorrect input data beyond their format (trying to register with the same email twice), etc.
I aim to unify errors handling and make it possible to early return errors to avoid deeply nested code and minimize the effort to handle exceptions. I like to wrap my route handlers with
enhanceHandler which is a higher order function that formats the output and sets the correct status based on the returned value from the actual route handler.
If you use TypeScript then start with defining the type for the route handler which allows specifying the type for params and body of the request.
Depending on the middleware you use it’s possible to extend Express request and add additional properties.
The essential part of the
enhanceHandler is utilizing Boom library. Boom is a set of factory functions for errors that correspond to HTTP errors. Boom, like Joi, is library made to use with Hapi.js but doesn’t depend on it.
To better understand each case that is handled by
enhanceHandler, read the tests on GitHub.
enhanceHandler just pass an actual route handler as a parameter and you can now return Boom errors from your controllers.
Whether you like this approach or not and consider it elegant as I do is the matter of preference. The most important is flexibility, so you adjust it to your liking. Hope you at least enjoy this poem:
Express is awesome, but Hapi is too.
Do not add more code out of the blue.
Combine the best tools and code just the glue.
You can buy me a coffee, I like a cold brew.
Originally published at michalzalecki.com on December 8, 2018.