Handling HTTP Status Codes Like a Pro with Boom & http-status

In a microservices-driven environment, where multiple services interact over HTTP, standardizing error status codes is essential. A well-defined approach to error handling not only improves debugging but also ensures seamless integration with front-end applications and mobile clients, enhancing the overall developer experience.

In this article, we will explore different modules and best practices to standardize HTTP status codes across all your Node.js microservices.

Understanding HTTP Status Codes

HTTP status codes are standardized responses that servers send to clients, indicating the outcome of an HTTP request. They are grouped into five categories:

  • 1xx (Informational): Request received, continuing process
  • 2xx (Success): Request successfully received, understood, and accepted
  • 3xx (Redirection): Further action needed to complete the request
  • 4xx (Client Error): Request contains bad syntax or cannot be fulfilled
  • 5xx (Server Error): Server failed to fulfill a valid request

Common status codes you’ll encounter include:

  • 200 – OK
  • 201 – Created
  • 204 – No Content
  • 400 – Bad Request
  • 401 – Unauthorized
  • 403 – Forbidden
  • 404 – Not Found
  • 500 – Internal Server Error

Basic HTTP Status Code Handling in Node.js

Typically, we handle status codes in Express.js applications like this:

const express = require('express');
const app = express();
const router = express.Router();

router.get('/', (req, res) => {
  res.send('OK'); // Sends HTTP status code 200 back to browser
});

router.all('*', (req, res) => {
  res.status(404).send('404 Invalid Request');
});

app.use('/', router);

app.listen(process.env.PORT || 3000);

The code above is a simple Node.js script that sends responses to the browser or API consumers.

We are handling status codes 200 and 404, but there are various other HTTP status codes assigned for different purposes.

For example, HTTP status code 401 indicates Unauthorized access, while 408 represents a Client timeout, and so on.

To handle all these status codes efficiently, there is a smart package called Boom, which helps standardize HTTP responses in your Node.js project.

Using Boom for Standardized HTTP Status Codes

Boom is a powerful library that helps create HTTP-friendly error objects with consistent structure. It provides methods to easily create response objects for each HTTP status code.

Installing Boom:

npm install boom --save

Basic Usage:

const express = require('express');
const app = express();
const Boom = require('boom');
const router = express.Router();

router.get('/', (req, res) => {
  res.send('OK'); // Sends HTTP status code 200 back to browser
});

router.get('/unauthorized', (req, res) => {
  // Creates a 401 Unauthorized response
  res.status(401).json(Boom.unauthorized('Authentication required').output.payload);
});

router.all('*', (req, res) => {
  // Creates a 404 Not Found response
  res.status(404).json(Boom.notFound('Invalid Request').output.payload);
});

app.use('/', router);

app.listen(process.env.PORT || 3000);

Enhanced Error Handling with Boom:

For more sophisticated error handling, you can create a middleware function:

const express = require('express');
const app = express();
const Boom = require('boom');

// Error handling middleware
function errorHandler(err, req, res, next) {
  if (Boom.isBoom(err)) {
    return res.status(err.output.statusCode).json(err.output.payload);
  }
  
  // For non-Boom errors, convert to Boom internal error
  const error = Boom.boomify(err, { statusCode: 500 });
  return res.status(error.output.statusCode).json(error.output.payload);
}

// Routes
app.get('/resource/:id', (req, res, next) => {
  try {
    const resource = findResource(req.params.id);
    if (!resource) {
      throw Boom.notFound(`Resource with id ${req.params.id} not found`);
    }
    res.json(resource);
  } catch (err) {
    next(err);
  }
});

// Apply error handling middleware
app.use(errorHandler);

app.listen(process.env.PORT || 3000);

Alternative: Using http-status npm Package

For a lighter approach focused specifically on status code constants, you can use the popular http-status package:

npm install http-status --save

This package provides a simple way to reference HTTP status codes by name:

const express = require('express');
const httpStatus = require('http-status');
const app = express();

app.get('/success', (req, res) => {
  res.status(httpStatus.OK).send({ 
    message: 'Success',
    status: httpStatus.OK
  });
});

app.get('/not-found', (req, res) => {
  res.status(httpStatus.NOT_FOUND).send({ 
    error: 'Not Found',
    message: 'The requested resource was not found',
    status: httpStatus.NOT_FOUND
  });
});

app.use((err, req, res, next) => {
  res.status(httpStatus.INTERNAL_SERVER_ERROR).send({
    error: 'Internal Server Error',
    message: err.message,
    status: httpStatus.INTERNAL_SERVER_ERROR
  });
});

app.listen(process.env.PORT || 3000);

The http-status package is lightweight and provides constants for all standard HTTP status codes, making your code more readable and maintainable.

Best Practices for HTTP Status Codes in Microservices

When implementing status codes across microservices, consider these best practices:

  1. Use appropriate status codes: Don’t default to 200 for everything or 500 for all errors.
  2. Include detailed error messages: Provide context about what went wrong.
  3. Add error codes: Consider including application-specific error codes for easier debugging.
  4. Standardize error response format: All microservices should return errors in the same structure.
  5. Document your error responses: Make sure your API documentation includes possible error responses.

Example Microservice Error Handling Scenarios

Here’s how to handle common microservice communication scenarios:

  1. Microservice is DOWN: Return 503 Service Unavailable
  2. Wrong URL: Return 404 Not Found
  3. Wrong arguments/validation failure: Return 400 Bad Request with validation details
  4. Resource not found in database: Return 404 Not Found
  5. Authentication failure: Return 401 Unauthorized
  6. Authorization failure: Return 403 Forbidden
  7. Unexpected errors: Return 500 Internal Server Error

Conclusion

Standardizing HTTP status codes across your Node.js microservices is essential for creating robust, maintainable applications. Whether you choose Boom for its comprehensive error formatting capabilities or http-status for a lighter approach, implementing a consistent error handling strategy will improve your application’s reliability and developer experience.

By following the practices outlined in this article, you’ll be handling HTTP status codes like a pro in no time!

Remember that proper error handling is not just about returning the right status code—it’s about providing meaningful information that helps both developers and end-users understand what went wrong and how to fix it.

Shahid
Shahid

Founder of Codeforgeek. Technologist. Published Author. Engineer. Content Creator. Teaching Everything I learn!

Articles: 128