Express Routing Basics
Introduction
Routing refers to how an application's endpoints (URIs) respond to client requests. In Express.js, routing is a fundamental concept that determines how your application handles different HTTP requests based on the request path and HTTP method.
Well-designed routes are essential for building organized, scalable web applications. They serve as the interface between client requests and your server's functionality, allowing you to create clear paths to different resources and actions in your application.
In this guide, we'll explore the basics of Express routing, from simple route definitions to more advanced routing patterns.
Basic Routing Concepts
Route Structure
An Express route consists of:
- An HTTP method (GET, POST, PUT, DELETE, etc.)
- A path pattern (like
/users
or/products/:id
) - A handler function that processes the request and sends a response
The basic syntax looks like this:
app.method(path, handler);
Where:
app
is an instance of Expressmethod
is an HTTP request method (lowercase)path
is the route path on the serverhandler
is the function executed when the route is matched
Your First Routes
Let's start with some simple route examples:
const express = require('express');
const app = express();
const port = 3000;
// Basic GET route
app.get('/', (req, res) => {
res.send('Hello World!');
});
// GET route with a different path
app.get('/about', (req, res) => {
res.send('About Us Page');
});
// POST route
app.post('/submit', (req, res) => {
res.send('Form submitted successfully!');
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
When running this server:
- Going to
http://localhost:3000/
in your browser returns "Hello World!" - Going to
http://localhost:3000/about
returns "About Us Page" - Sending a POST request to
http://localhost:3000/submit
returns "Form submitted successfully!"
Route Parameters
Often, you'll need to capture values from the URL. For instance, when displaying a specific user or product. Express allows you to define route parameters using the :paramName
syntax.
// Route with a parameter
app.get('/users/:userId', (req, res) => {
res.send(`You requested information about user: ${req.params.userId}`);
});
// Multiple parameters
app.get('/products/:category/:id', (req, res) => {
const { category, id } = req.params;
res.send(`You requested the product ${id} in category ${category}`);
});
Examples:
http://localhost:3000/users/123
will return "You requested information about user: 123"http://localhost:3000/products/electronics/laptop
will return "You requested the product laptop in category electronics"
Route Handlers
Route handlers are functions that execute when a matching route is found. They have access to:
req
(the request object)res
(the response object)next
(a function to pass control to the next matching route)
Multiple Handlers
You can provide multiple callback functions for a route. Just make sure to call next()
to pass control to the next handler.
app.get('/example',
(req, res, next) => {
console.log('First handler');
next(); // Pass control to the next handler
},
(req, res) => {
console.log('Second handler');
res.send('Response from the second handler');
}
);
Response Methods
Express provides several methods for responding to requests:
// Sending basic text
app.get('/text', (req, res) => {
res.send('Plain text response');
});
// Sending HTML
app.get('/html', (req, res) => {
res.send('<h1>HTML Response</h1><p>This is HTML content</p>');
});
// Sending JSON
app.get('/api/data', (req, res) => {
res.json({
name: 'John',
age: 30,
city: 'New York'
});
});
// Setting status code
app.get('/not-found', (req, res) => {
res.status(404).send('Resource not found');
});
// Redirecting
app.get('/old-page', (req, res) => {
res.redirect('/new-page');
});
// Downloading a file
app.get('/download', (req, res) => {
res.download('./files/report.pdf', 'user-report.pdf');
});
Route Organization with Express Router
As your application grows, putting all routes in your main file becomes unmanageable. Express Router helps you modularize your routes.
Here's how to create route modules:
// userRoutes.js
const express = require('express');
const router = express.Router();
// Routes defined relative to the mount point
router.get('/', (req, res) => {
res.send('Users list');
});
router.get('/:id', (req, res) => {
res.send(`User with ID: ${req.params.id}`);
});
router.post('/', (req, res) => {
res.send('Create a new user');
});
module.exports = router;
Then in your main app file:
// app.js
const express = require('express');
const userRoutes = require('./userRoutes');
const app = express();
// Mount the router at /users
app.use('/users', userRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Now, the routes are accessible at:
/users
- Returns "Users list"/users/123
- Returns "User with ID: 123"- POST to
/users
- Returns "Create a new user"
Route Path Patterns
Express supports different path patterns:
String Paths
The simplest form of route paths:
app.get('/about', (req, res) => {
res.send('About page');
});
String Patterns with Wildcards
You can use string patterns with special characters:
// Match acd or abcd
app.get('/ab?cd', (req, res) => {
res.send('ab?cd pattern matched');
});
// Match abcd, abbcd, abbbcd, etc.
app.get('/ab+cd', (req, res) => {
res.send('ab+cd pattern matched');
});
// Match abcd, abxcd, ab123cd, etc.
app.get('/ab*cd', (req, res) => {
res.send('ab*cd pattern matched');
});
Regular Expressions
For complex matching, you can use regular expressions:
// Match any route that ends with 'fly'
app.get(/.*fly$/, (req, res) => {
res.send('Route ends with "fly"');
});
Practical Example: Building a Simple API
Let's build a simple API for a blog with Express routing:
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json()); // For parsing application/json
// Sample data
let posts = [
{ id: 1, title: 'Introduction to Express', content: 'Express is a web framework for Node.js' },
{ id: 2, title: 'REST API with Express', content: 'Building RESTful APIs with Express is easy' }
];
// GET all posts
app.get('/api/posts', (req, res) => {
res.json(posts);
});
// GET a specific post
app.get('/api/posts/:id', (req, res) => {
const post = posts.find(p => p.id === parseInt(req.params.id));
if (!post) return res.status(404).send('Post not found');
res.json(post);
});
// CREATE a new post
app.post('/api/posts', (req, res) => {
const post = {
id: posts.length + 1,
title: req.body.title,
content: req.body.content
};
posts.push(post);
res.status(201).json(post);
});
// UPDATE a post
app.put('/api/posts/:id', (req, res) => {
const post = posts.find(p => p.id === parseInt(req.params.id));
if (!post) return res.status(404).send('Post not found');
post.title = req.body.title;
post.content = req.body.content;
res.json(post);
});
// DELETE a post
app.delete('/api/posts/:id', (req, res) => {
const postIndex = posts.findIndex(p => p.id === parseInt(req.params.id));
if (postIndex === -1) return res.status(404).send('Post not found');
const deletedPost = posts.splice(postIndex, 1);
res.json(deletedPost[0]);
});
app.listen(port, () => {
console.log(`Blog API running at http://localhost:${port}`);
});
This example implements a CRUD (Create, Read, Update, Delete) API for blog posts using different HTTP methods and routes.
Summary
In this guide, we covered the essentials of Express routing:
- Basic route structure and syntax
- Route parameters for dynamic paths
- Response methods to handle different output types
- Route organization with Express Router
- Route path patterns including string paths and regular expressions
- A practical example of building a RESTful API
Understanding routing is key to building effective Express applications. With these fundamentals, you can create organized, maintainable web applications and APIs.
Additional Resources
Practice Exercises
- Create a simple Express app with routes for a homepage, about page, and contact page.
- Build a REST API for a "todo" application with routes to list, add, update, and delete tasks.
- Refactor an existing Express app to use Express Router for better organization.
- Create a route with multiple parameters (like
/products/:category/:id/:color
) and extract all parameters in the handler. - Implement a "catch-all" route that handles requests for non-existent routes with a custom 404 page.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)