Middlewares
Comprehensive guide to understanding and using middlewares in ExpressJS for request handling, processing, and routing control.
Middlewares in ExpressJS
In ExpressJS, a middleware is a function that has access to the request object (req), the response object (res), and the next middleware function in the application's request-response cycle.
Middlewares can:
- Execute any code.
- Modify
reqandresobjects. - End the request-response cycle.
- Call the next middleware in the stack.
Middleware Signature
A middleware function looks like this:
function middleware(req, res, next) {
// Perform operations
next(); // Pass control to the next middleware
}req: The incoming request object.res: The outgoing response object.next: Function to pass control to the next middleware.
Types of Middleware
1. Application-Level Middleware
Defined using app.use() or HTTP methods like app.get(), app.post().
const express = require('express');
const app = express();
// Simple logging middleware
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});2. Router-Level Middleware
Attached to an express.Router() instance.
const express = require('express');
const router = express.Router();
// Router-specific middleware
router.use((req, res, next) => {
console.log('Router middleware');
next();
});
router.get('/items', (req, res) => {
res.send('List of items');
});
app.use('/api', router);3. Error-Handling Middleware
Error-handling middleware has four arguments: (err, req, res, next).
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});Always defined after other middlewares and routes.
4. Built-In Middleware
Express provides some built-in middleware like:
express.static(): Serves static files.express.json(): Parses incoming JSON payload.express.urlencoded(): Parses URL-encoded payload.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));5. Third-Party Middleware
Popular middlewares from npm:
morgan: HTTP request logger.cors: Enables Cross-Origin Resource Sharing.helmet: Adds security-related HTTP headers.
with Morgan
const morgan = require('morgan');
app.use(morgan('dev'));Middleware in Route Syntax (app.get, app.post, etc.)
Middlewares can be directly passed in the route definition.
function checkAuth(req, res, next) {
const token = req.headers['authorization'];
if (token === 'valid-token') {
next();
} else {
res.status(401).json({ message: 'Unauthorized' });
}
}
app.get('/dashboard', checkAuth, (req, res) => {
res.send('Welcome to your dashboard');
});checkAuthruns first.- If
checkAuthcallsnext(), the final handler executes. - If not, the response ends early.
You can chain multiple middlewares:
function logRequest(req, res, next) {
console.log(`${req.method} ${req.url}`);
next();
}
function checkAdmin(req, res, next) {
const isAdmin = req.headers['admin'] === 'true';
if (isAdmin) {
next();
} else {
res.status(403).send('Forbidden');
}
}
app.get('/admin', logRequest, checkAdmin, (req, res) => {
res.send('Welcome, Admin');
});Controlling the Flow
A middleware can decide whether to:
-
Pass control to the next middleware:
function logger(req, res, next) { console.log('Logging request'); next(); } -
End the request-response cycle:
function blockRequest(req, res, next) { res.status(403).send('Access Denied'); // No next() call, request ends here }
Middleware Ordering Matters
Middlewares are executed in the order they are added.
app.use(middlewareOne);
app.use(middlewareTwo);
app.get('/path', (req, res) => res.send('Done'));middlewareOne runs first, then middlewareTwo, then the route handler.
Practical Example
const express = require('express');
const app = express();
app.use(express.json());
// Authentication middleware
function authMiddleware(req, res, next) {
const token = req.headers['authorization'];
if (token === 'valid-token') {
next();
} else {
res.status(401).json({ message: 'Unauthorized' });
}
}
// Apply authMiddleware to protected routes
app.use('/protected', authMiddleware);
app.get('/protected/data', (req, res) => {
res.json({ secret: 'This is protected data' });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});Best Practices
- Keep middlewares small and single-purpose.
- Place error-handling middleware last.
- Use third-party middlewares for common tasks.
- Avoid blocking the event loop (no heavy synchronous tasks).
- Use
next(err)to delegate error handling. - Don’t forget to call
next()unless the response ends.
Router
Comprehensive guide to using Express Router for modular route handling in Node.js applications, including detailed examples, route parameters, middleware usage, and best practices.
Common Middlewares
A detailed guide covering commonly used middlewares in ExpressJS for handling requests, security, logging, CORS, and body parsing.