- Express.js Basics
- Express.js HOME
- Express.js Introduction
- Express.js Installation
- Express.js Basic App
- Express.js Routing
- Basics Routing
- Route Parameters
- Handling Query Strings
- Router Middleware
- Middleware
- What is Middleware?
- Application-Level Middleware
- Router-Level Middleware
- Built-In Middleware
- Error-Handling Middleware
- Third-Party Middleware
- Express.js HTTP
- Handling GET Requests
- Handling POST Requests
- Handling PUT Requests
- Handling DELETE Requests
- Templating Engines
- Using Templating Engines
- Setting Up EJS
- Setting Up Handlebars
- Setting Up Pug
- Request/Response
- Request Object
- Response Object
- Handling JSON Data
- Handling Form Data
- Static Files
- Serving Static Files
- Setting Up Static Folders
- Managing Assets
- Express.js Advanced
- Middleware Stack
- CORS in Express.js
- JWT Authentication
- Session Handling
- File Uploads
- Error Handling
- Databases
- Express.js with MongoDB
- MongoDB CRUD Operations
- Express.js with MySQL
- MySQL CRUD Operations
- Deployment
- Deploying Express.js Apps to Heroku
- Deploying Express.js Apps to AWS
- Deploying Express.js Apps to Vercel
Express.js Router Middleware
In Express.js, middleware is the backbone of your application. Think of it as a series of "checkpoints" or "stages" that a request passes through before it finally reaches your route handler. Router middleware specifically allows you to scope these checkpoints to specific groups of routes, making your code cleaner and more modular.
Whether you need to check if a user is logged in, log incoming requests for debugging, or parse complex data, router middleware provides a structured way to handle these tasks without repeating code across every single route.
Key Features of Router Middleware
- Route-specific Scoping: Unlike global middleware that runs on every single request to your server, router middleware can be restricted to specific paths (like
/apior/admin). - Stacked Execution: You can chain multiple middleware functions together. Express will execute them one after another in the exact order they are defined.
- Modular Architecture: By using
express.Router(), you can move your route logic into separate files, keeping your mainapp.jsfile lean and readable.
Steps to Use Router Middleware in Express.js
1. Set up a Basic Express Application
First, prepare your environment. Initialize your project and install the necessary Express package:
npm init -y
npm install express --save
2. Create an Express Application with Router Middleware
In this example, we will create a dedicated router for user-related actions. We'll add middleware that only triggers when someone accesses a /user URL.
const express = require('express');
const app = express();
const router = express.Router();
// 1. Global Middleware: Runs for every single request to the server
const logRequest = (req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} to ${req.originalUrl}`);
next(); // Essential: Tell Express to move to the next function
};
app.use(logRequest);
// 2. Router-Level Middleware: Only runs for routes attached to this router
router.use((req, res, next) => {
console.log('Accessing the /user sub-section...');
// Example: You could check for an API key here
next();
});
// Define a route for fetching a user by ID
router.get('/:id', (req, res) => {
res.send(`User Profile Page for ID: ${req.params.id}`);
});
// Define a route for updating user data
router.put('/:id', (req, res) => {
res.send(`Updated data for user: ${req.params.id}`);
});
// 3. Mount the router: All routes in 'router' now start with '/user'
app.use('/user', router);
app.listen(3000, () => {
console.log('Server is live at http://localhost:3000');
});
next() at the end of your middleware. If you forget, the request will hang indefinitely and the browser will eventually time out because the cycle never finished.
3. Run the Application
Launch your server using Node.js:
node app.js
4. Test the Routes
Use a browser or a tool like Postman to see the middleware in action:
- GET
http://localhost:3000/user/123– You will see the profile message in the browser, and two logs in your terminal (the global log and the user-specific log). - PUT
http://localhost:3000/user/123– This tests the update logic.
Handling Error Middleware
Error handling middleware is unique because it takes four arguments instead of three. Express identifies it specifically by this signature: (err, req, res, next). You should place this at the very end of your middleware stack.
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Internal Server Error: Something broke on our end!');
});
Using Middleware with Specific Route Handlers
You don't always want middleware to run for every route in a router. Sometimes, you only want it for a single endpoint—for example, a "Dashboard" page that requires authentication.
// A mock authentication guard
const checkAuth = (req, res, next) => {
const isAuthorized = true; // Replace with actual logic
if (isAuthorized) {
next();
} else {
res.status(403).send('Unauthorized Access');
}
};
// Apply checkAuth ONLY to the /profile route
router.get('/profile', checkAuth, (req, res) => {
res.send('Welcome to your private profile');
});
Router Middleware with Parameters
The router.param() function is incredibly useful for "pre-loading" data. If multiple routes use the same :id parameter, you can write the logic once to fetch that data from a database and attach it to the request object.
// This runs whenever ':id' is present in the URL
router.param('id', (req, res, next, id) => {
console.log(`Pre-loading data for user ID: ${id}`);
// You could fetch a user from a DB here
req.user = { id: id, name: 'John Doe' };
next();
});
router.get('/:id', (req, res) => {
// Access the pre-loaded data from req.user
res.send(`User: ${req.user.name} (ID: ${req.user.id})`);
});
Summary
Router middleware is an essential tool for building professional Express applications. It allows you to create a logical "flow" for your requests, ensuring tasks like logging, security, and data validation happen automatically before your main logic runs. By mastering the use of next(), error-handling middleware, and router.param(), you can build APIs that are much easier to maintain and scale over time.