DEV Community

Abhinav
Abhinav

Posted on

Understanding HTTP Status Codes with Express and Morgan

When building and testing web applications, handling HTTP status codes effectively is crucial for communication between the server and the client. These status codes indicate the success or failure of a request and help the client understand how to respond.

In this blog, we’ll explore how to implement various HTTP status codes in a simple Express application. We’ll also use Morgan, a popular logging middleware, to log all incoming requests and their associated status codes.

What Are HTTP Status Codes?

HTTP status codes are three-digit numbers sent by the server in response to a client’s request. They are categorized as follows:

  • 1xx (Informational): Request received, continuing process.
  • 2xx (Success): The request was successfully received, understood, and accepted.
  • 3xx (Redirection): The client must take additional action to complete the request.
  • 4xx (Client Error): The client’s request contains bad syntax or cannot be fulfilled.
  • 5xx (Server Error): The server failed to fulfill a valid request.

Common examples include:

  • 200 OK: The request was successful.
  • 404 Not Found: The requested resource could not be found.
  • 500 Internal Server Error: The server encountered an unexpected condition.

Let's now dive into how to handle these status codes in an Express app.

Setting Up an Express App with Morgan

Morgan is a middleware that logs HTTP requests and responses. It helps developers track server activity, including which routes are hit and which status codes are returned.

Step 1: Install Dependencies

First, create a new Node.js project and install the necessary packages:

mkdir express-status-demo
cd express-status-demo
npm init -y
npm install express morgan
Enter fullscreen mode Exit fullscreen mode

Step 2: Create an Express App with Different Status Codes

Here’s an example of an Express app that returns different HTTP status codes for various routes. We’ll use Morgan to log the details of each request.

const express = require('express');
const morgan = require('morgan');
const fs = require('fs');
const path = require('path');

const app = express();

// Log requests to the console
app.use(morgan('dev'));

// Create a log file stream for logging requests
const accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' });
app.use(morgan('combined', { stream: accessLogStream }));

// Route for 200 OK (Success)
app.get('/', (req, res) => {
  res.status(200).send('Everything is OK');
});

// Route for 201 Created
app.post('/create', (req, res) => {
  res.status(201).send('Resource created');
});

// Route for 400 Bad Request
app.get('/bad-request', (req, res) => {
  res.status(400).send('Bad Request');
});

// Route for 401 Unauthorized
app.get('/unauthorized', (req, res) => {
  res.status(401).send('Unauthorized');
});

// Route for 403 Forbidden
app.get('/forbidden', (req, res) => {
  res.status(403).send('Forbidden');
});

// Route for 404 Not Found
app.get('/not-found', (req, res) => {
  res.status(404).send('Resource not found');
});

// Route for 500 Internal Server Error
app.get('/error', (req, res) => {
  res.status(500).send('Internal Server Error');
});

// Start the server
const port = 3000;
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Step 3: Running the Application

To run the application, simply execute:

node index.js
Enter fullscreen mode Exit fullscreen mode

Your server will start running on http://localhost:3000, and you can test the various routes to see how they handle different status codes.

Step 4: Testing the Routes

Now, let's access the various routes in the app and observe the behavior.

  • 200 OK: Visit http://localhost:3000/ to get the "Everything is OK" message and a 200 status.
  • 201 Created: Simulate resource creation by making a POST request to /create. This will return a 201 status with the message "Resource created".

Resource created

Step 5: Checking the Logs

Morgan logs each request and its status code to both the console and a file named access.log in the project directory.

Example log output:

::ffff:127.0.0.1 - - [16/Oct/2024:05:02:33 +0000] "GET / HTTP/1.1" 200 12 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0"
::ffff:127.0.0.1 - - [16/Oct/2024:05:02:33 +0000] "GET /favicon.ico HTTP/1.1" 404 150 "http://localhost:3000/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:131.0) Gecko/20100101 Firefox/131.0"
Enter fullscreen mode Exit fullscreen mode

logsOutput

Each entry in the log shows the IP address, request method, URL, HTTP status code, and other details like the browser’s User-Agent. In this case, we can see a successful 200 OK request to the home page and a 404 Not Found request for the favicon.

Conclusion

Handling HTTP status codes properly is essential for building a robust web application. In this example, we explored how to configure different status codes in an Express app and log them using Morgan. By understanding these status codes, you can ensure better communication between the server and client, improving the overall user experience.

Would you like to learn more about error handling in Express or explore how to write custom error messages for different status codes? Let me know in the comments below!


Top comments (0)