Skip to main content
Express.js Tutorial
CHAPTER 07 Beginner

Middleware in Express.js

Updated: May 14, 2026
25 min read

# CHAPTER 7

Middleware in Express.js

1. Introduction

If you understand Middleware, you understand Express.js. Middleware functions are the unsung heroes of your application. They are functions that intercept incoming HTTP requests, inspect them, modify them, log them, or block them entirely before they ever reach your core routing logic. In this chapter, we will demystify middleware, explore built-in Express tools, and write our own custom interceptors.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define the concept and anatomy of an Express Middleware function.
  • Understand the critical importance of the next() function.
  • Implement Global Middleware using app.use().
  • Implement Route-Specific Middleware (e.g., protecting a route).

3. Beginner-Friendly Explanation

Imagine an exclusive VIP nightclub.
  • The Customer: The incoming HTTP Request.
  • The Dance Floor: Your API Route Logic (res.json(...)).
  • The Bouncers: The Middleware.

Before the customer can reach the dance floor, they must walk down a hallway lined with bouncers.

  1. 1. Bouncer 1 (Logger): Writes down the customer's name and arrival time in a ledger, then says "Go ahead" (next()).
  1. 2. Bouncer 2 (Security): Checks if the customer is carrying anything dangerous. If safe, says "Go ahead" (next()).
  1. 3. Bouncer 3 (Authentication): Checks if the customer has a VIP wristband. If they do, they enter the dance floor. If they don't, the bouncer physically throws them out the front door (res.status(401)), and they never reach the dance floor.

4. Anatomy of a Middleware Function

A middleware function looks exactly like a standard route, but it has a third argument: next.
javascript
1234567
const myFirstMiddleware = (req, res, next) => {
    console.log("A request just arrived!");
    
    // CRITICAL: You MUST call next() to pass the request to the next bouncer/route.
    // If you forget next(), the request hangs forever!
    next(); 
};

5. Global Middleware

To apply middleware globally (to every single route in your application), we use app.use().

Let's build a Custom Logger:

javascript
123456789101112131415161718
const express = require('express');
const app = express();

// Custom Global Middleware
const requestLogger = (req, res, next) => {
    const time = new Date().toLocaleTimeString();
    // Logs: "[10:05 AM] GET request made to /api/users"
    console.log(`[${time}] ${req.method} request made to ${req.url}`);
    
    next(); // Pass control to the next function
};

// Apply it globally
app.use(requestLogger);

app.get('/api/users', (req, res) => {
    res.send("Here are the users");
});

6. Route-Specific Middleware

You don't want a security check to run globally; guests need to see the public homepage! You only want the security check to run on private routes.

Let's build a Fake Authentication Middleware:

javascript
123456789101112131415161718
const checkApiKey = (req, res, next) => {
    const userKey = req.query.api_key;
    const secretKey = "super_secret_123";

    if (userKey === secretKey) {
        // Success! They have the wristband. Let them pass.
        next();
    } else {
        // Failure! Throw them out. DO NOT call next().
        res.status(401).json({ error: "Unauthorized! Invalid API Key." });
    }
};

// Apply it ONLY to this specific route by placing it in the middle
app.get('/api/dashboard', checkApiKey, (req, res) => {
    // This code ONLY executes if next() was called in the middleware!
    res.json({ message: "Welcome to the secret VIP dashboard." });
});

*To test this: Visiting /api/dashboard fails with 401. Visiting /api/dashboard?apikey=supersecret_123 succeeds with 200.*

7. Built-in Express Middleware

Express comes with powerful middleware out of the box. The most important one is express.json(). If a client sends a JSON payload to your server, Express is blind to it by default. You must add app.use(express.json()) at the top of your file to tell Express to intercept the payload and attach it to the req.body object.

8. Backend Workflow: Modifying the Request

Middleware can do more than just block traffic; it can alter the request before the Route sees it. For example, an Authentication middleware can find the logged-in user in the database, and attach the user object directly to the request: req.user = dbUser; next();. Now, the final Route instantly knows exactly who is logged in!

9. Best Practices

  • Order of Execution: In Express, order matters absolutely. Express reads your app.js file from top to bottom. If you define a Route *above* your Global Logger Middleware, the Request hits the route, sends the Response, and the Logger is entirely ignored! Always put app.use() Global Middlewares at the very top of your file.

10. Common Mistakes

  • Forgetting next(): If your custom middleware doesn't end with res.json() (throwing an error) or next() (passing it on), the request becomes trapped in purgatory. The client's browser will spin indefinitely.

11. Exercises

  1. 1. Explain the "Bouncer Analogy" and how the next() function operates within an Express application. What happens if next() is never called?

12. Coding Challenges

  • Challenge: Write a custom route-specific middleware called checkAge. It should check a query string ?age=X. If the age is less than 18, it should return a 403 Forbidden status with a JSON error message. Apply this middleware to a route named /api/restricted-content.

13. MCQs with Answers

Question 1

In an Express middleware function (req, res, next), what happens if you successfully validate the request but forget to call the next() function?

Question 2

How do you apply a middleware function so that it intercepts EVERY incoming HTTP request to your entire Express application?

14. Interview Questions

  • Q: Explain the Request-Response lifecycle in Express, specifically detailing how multiple middleware functions (a "middleware stack") are executed in sequence.
  • Q: Provide a real-world scenario where a custom middleware would modify the req object before calling next(), and explain how the subsequent route utilizes that modification.

15. FAQs

Q: Can I use third-party middleware? A: Absolutely! The Node ecosystem provides amazing pre-built middleware via NPM. Examples include cors (for cross-origin requests), helmet (for security headers), and morgan (for professional logging).

16. Summary

In Chapter 7, we unlocked the true architectural power of Express. Middleware acts as a series of customizable checkpoints. By writing Global Middleware, we can log traffic or enforce security across our entire app. By writing Route-Specific Middleware, we can enforce strict authorization rules on sensitive endpoints, ensuring our core routing logic remains clean and protected.

17. Next Chapter Recommendation

We know how to send JSON data, but what if we need to send actual HTML pages, images, and CSS files to the browser? Proceed to Chapter 8: Serving Static Files and Templates.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·