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
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}`);
});
Step 3: Running the Application
To run the application, simply execute:
node index.js
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".
- 400 Bad Request: Access http://localhost:3000/bad-request to simulate a client error and get a 400 status.
- 401 Unauthorized: Access http://localhost:3000/unauthorized for a 401 Unauthorized status.
- 403 Forbidden: Access http://localhost:3000/forbidden to trigger a 403 Forbidden status.
- 404 Not Found: Visit http://localhost:3000/not-found for a 404 error.
- 500 Internal Server Error: Access http://localhost:3000/error to simulate a server error and receive a 500 status.
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"
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)