how-to-create-and-use-custom-middleware-in-expressjs.html

How to Create and Use Custom Middleware in Express.js

Express.js is one of the most popular web frameworks for Node.js, known for its simplicity and flexibility. One of the key features that make Express powerful is its middleware system. In this article, we’ll explore how to create and use custom middleware in Express.js, providing you with the tools to optimize your application and streamline your code.

What is Middleware?

In the context of Express.js, middleware refers to functions that are executed during the request-response cycle. These functions can modify the request and response objects, end the request-response cycle, or call the next middleware in the stack. Middleware can be used for various purposes, such as:

  • Logging requests: Keeping track of incoming requests to debug issues.
  • Authentication: Verifying user identity before granting access to certain resources.
  • Error handling: Centralizing error management for better code organization.
  • Data parsing: Automatically processing incoming data formats like JSON.

Why Create Custom Middleware?

While Express comes with built-in middleware, creating custom middleware allows you to tailor functionality specific to your application’s needs. Custom middleware can help you:

  • Encapsulate functionality: Group related logic in one place for better readability and maintenance.
  • Reuse code: Apply the same logic across multiple routes without redundancy.
  • Enhance performance: Optimize specific operations to improve application efficiency.

Step-by-Step Guide to Creating Custom Middleware

Step 1: Set Up Your Express Application

First, ensure you have Node.js and Express installed. If you don’t have Express set up yet, you can create a new project by following these commands in your terminal:

mkdir express-middleware-example
cd express-middleware-example
npm init -y
npm install express

Next, create a new file called app.js:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// Basic route for testing
app.get('/', (req, res) => {
    res.send('Welcome to Express Middleware Example!');
});

app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Step 2: Creating Custom Middleware

Let’s create a custom middleware that logs the details of each incoming request. You can define middleware by creating a function that takes three parameters: req, res, and next.

// Custom middleware to log request details
const requestLogger = (req, res, next) => {
    console.log(`${req.method} request made to: ${req.url}`);
    next(); // Pass control to the next middleware or route handler
};

// Use the custom middleware
app.use(requestLogger);

Step 3: Implementing Middleware in Your Application

Place the middleware function before your route definitions to ensure it runs for every request. Here’s the updated app.js file:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// Custom middleware to log request details
const requestLogger = (req, res, next) => {
    console.log(`${req.method} request made to: ${req.url}`);
    next();
};

// Use the custom middleware
app.use(requestLogger);

// Basic route for testing
app.get('/', (req, res) => {
    res.send('Welcome to Express Middleware Example!');
});

app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Step 4: Adding More Functionality

You can create additional middleware for various tasks. For example, let’s create middleware that checks if a user is authenticated:

const isAuthenticated = (req, res, next) => {
    // Simulate authentication check
    const isAuthenticated = false; // Change to `true` to simulate a logged-in user

    if (isAuthenticated) {
        next(); // User is authenticated, proceed to the next middleware
    } else {
        res.status(401).send('Unauthorized: You must log in first.');
    }
};

// Protect a specific route
app.get('/protected', isAuthenticated, (req, res) => {
    res.send('Welcome to the protected route!');
});

Step 5: Error Handling Middleware

Error handling is crucial for any application. You can create custom error-handling middleware by defining a function with four parameters: err, req, res, and next.

// Error handling middleware
const errorHandler = (err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something went wrong!');
};

// Use the error handling middleware after all routes
app.use(errorHandler);

Complete Example

Here’s the complete app.js file that includes all the middleware we’ve discussed:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

const requestLogger = (req, res, next) => {
    console.log(`${req.method} request made to: ${req.url}`);
    next();
};

const isAuthenticated = (req, res, next) => {
    const isAuthenticated = false; // Change to `true` for testing
    if (isAuthenticated) {
        next();
    } else {
        res.status(401).send('Unauthorized: You must log in first.');
    }
};

const errorHandler = (err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something went wrong!');
};

app.use(requestLogger);

app.get('/', (req, res) => {
    res.send('Welcome to Express Middleware Example!');
});

app.get('/protected', isAuthenticated, (req, res) => {
    res.send('Welcome to the protected route!');
});

app.use(errorHandler);

app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Conclusion

Creating and using custom middleware in Express.js allows you to enhance your application's functionality, code organization, and performance. By following the steps outlined in this article, you can implement logging, authentication, and error handling middleware effectively. As you develop your applications, consider how middleware can simplify your code and improve user experience. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.