Skip to main content

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:

  1. An HTTP method (GET, POST, PUT, DELETE, etc.)
  2. A path pattern (like /users or /products/:id)
  3. A handler function that processes the request and sends a response

The basic syntax looks like this:

javascript
app.method(path, handler);

Where:

  • app is an instance of Express
  • method is an HTTP request method (lowercase)
  • path is the route path on the server
  • handler is the function executed when the route is matched

Your First Routes

Let's start with some simple route examples:

javascript
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.

javascript
// 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.

javascript
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:

javascript
// 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:

javascript
// 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:

javascript
// 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:

javascript
app.get('/about', (req, res) => {
res.send('About page');
});

String Patterns with Wildcards

You can use string patterns with special characters:

javascript
// 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:

javascript
// 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:

javascript
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

  1. Create a simple Express app with routes for a homepage, about page, and contact page.
  2. Build a REST API for a "todo" application with routes to list, add, update, and delete tasks.
  3. Refactor an existing Express app to use Express Router for better organization.
  4. Create a route with multiple parameters (like /products/:category/:id/:color) and extract all parameters in the handler.
  5. 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! :)