Middleware is the backbone of Express.js applications, acting as a bridge between incoming requests and final responses. Whether you’re handling authentication, logging, or data validation, custom middleware helps you write cleaner, reusable code. In this guide, you’ll learn how to create your own middleware in Node.js using Express.js — even if you’re a beginner!
Table of Contents
- What is Middleware?
- Prerequisites
- Types of Middleware in Express
- Step-by-Step: Building Custom Middleware
- Practical Examples
- Best Practices
- Conclusion
What is Middleware?
Middleware functions are functions that have access to the request object (req
), response object (res
), and the next()
function in the application’s request-response cycle. They can:
- Execute any code.
- Modify
req
andres
objects. - End the request-response cycle.
- Call the next middleware using
next()
.
Think of middleware as a chain of security guards checking your ID before letting you into a club. Each guard (middleware) performs a specific task before passing you to the next one.
Prerequisites
Before diving in, ensure you have:
- Node.js and npm installed.
- Basic knowledge of JavaScript.
- Express.js installed (run
npm install express
if not).
Types of Middleware in Express
Express supports five types of middleware:
- Application-level middleware (e.g.,
app.use()
). - Router-level middleware (similar but bound to
express.Router()
). - Error-handling middleware (has four arguments:
err, req, res, next
). - Built-in middleware (e.g.,
express.json()
). - Third-party middleware (like
cors
ormorgan
).
We’ll focus on creating application-level middleware and error-handling middleware.
How to Setup a Project and Send Email in Node.js Using Nodemailer & Gmail
Step-by-Step: Building Custom Middleware
Step 1: Set Up a Basic Express App
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});
Step 2: Create a Simple Logging Middleware
Add this before your routes:
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next(); // Pass control to the next middleware/route
});
Now, every request will log its timestamp, method, and URL.
Step 3: Build Authentication Middleware
const authMiddleware = (req, res, next) => {
const apiKey = req.headers['x-api-key'];
if (apiKey === 'MY_SECRET_KEY') {
next(); // Authorized
} else {
res.status(401).send('Unauthorized!');
}
};
// Apply to a specific route
app.get('/admin', authMiddleware, (req, res) => {
res.send('Welcome to the admin panel!');
});
Practical Examples
Example 1: Error-Handling Middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
Example 2: Route-Specific Middleware
// Apply middleware only to /api routes
const router = express.Router();
router.use((req, res, next) => {
console.log('API request received');
next();
});
router.get('/users', (req, res) => {
res.send('List of users');
});
app.use('/api', router);
Best Practices
- Keep Middleware Focused: Each middleware should do one task (e.g., logging, auth).
- Order Matters: Middleware executes in the order they’re defined.
- Always Call
next()
: Unless you’re ending the request (like sending an error). - Use Error-Handling Middleware: Place it last after other routes/middleware.
- Test Thoroughly: Middleware affects all downstream code.
Conclusion
Creating custom middleware in Express.js is straightforward once you understand the request-response cycle. Start with simple tasks like logging, then move to complex logic like authentication. By following the examples and best practices above, you’ll build scalable, maintainable Node.js applications.
Ready to level up your Express skills? Try building middleware for rate limiting or request validation next! Don’t forget to share this guide if you found it helpful 😊.