Building Web Servers with Express: Routing and Middleware Explained
Express is a web application framework for Node.js, designed for building web servers and APIs efficiently. It simplifies development compared to using Node.js's native http module directly, similar to how jQuery abstracts browser APIs.
Setting Up Express
Install Express in your project directory:
npm install express
Create a basic web server:
const express = require('express');
const server = express();
server.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});
Handling Requests
Define routes for GET and POST requests:
server.get('/example', (request, response) => {
response.send('GET request handled');
});
server.post('/example', (request, response) => {
response.send('POST request handled');
});
Access query parameters and dynamic URL segments:
server.get('/search', (req, res) => {
console.log(req.query); // Query string parameters
res.send(req.query);
});
server.get('/items/:itemId', (req, res) => {
console.log(req.params.itemId); // Dynamic parameter
res.send(`Item ID: ${req.params.itemId}`);
});
Serving Static Files
Use express.static() to serve static resources:
server.use(express.static('assets'));
Files in the assets directory are accessible directly, e.g., http://localhost:3000/image.png.
To add a path prefix:
server.use('/static', express.static('assets'));
Now access files via http://localhost:3000/static/image.png.
Routing in Express
Routes map HTTP methods and URLs to handler functions:
server.get('/home', (req, res) => {
res.send('Home page');
});
Routes are matched in order; both method and URL must match.
Modular Routing
Create separate routing modules for better organization:
routes.js:
const express = require('express');
const router = express.Router();
router.get('/list', (req, res) => {
res.send('Item list');
});
router.post('/add', (req, res) => {
res.send('Item added');
});
module.exports = router;
Main file:
const routes = require('./routes');
server.use('/api', routes);
Acces routes at /api/list and /api/add.
Middleware in Express
Middleware functions process requests before they reach route handlers. They receive req, res, and next parameters.
Global Middleware
Apply middleware to all routes:
server.use((req, res, next) => {
console.log('Request received');
next();
});
Local Middleware
Apply middleware to specific routes:
const logRequest = (req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
};
server.get('/secure', logRequest, (req, res) => {
res.send('Secure area');
});
Error-Handling Middleware
Define error handlers with four parameters:
server.get('/error', (req, res) => {
throw new Error('Test error');
});
server.use((err, req, res, next) => {
console.error(err.message);
res.status(500).send('Server error');
});
Built-in Middleware
Express provides middleware for common tasks:
server.use(express.json()); // Parse JSON request bodies
server.use(express.urlencoded({ extended: true })); // Parse URL-encoded data
Third-Party Middleware
Install and use external middleware, e.g., body-parser for older Express vertions:
npm install body-parser
const bodyParser = require('body-parser');
server.use(bodyParser.urlencoded({ extended: true }));
Key Points
- Register middleware before routes to ensure processing.
- Call
next()to pass control to the next middleware or route. - Middleware shares
reqandresobjects across request lifecycle. - Use modular routing for scalable applications.
- Error handlers must be defined after all routes.
Development Tools
Use nodemon for automatic server restarts during development:
npm install -g nodemon
nodemon server.js