Skip to main content

Express Routes Introduction

What is Routing in Express?

Routing refers to how an application's endpoints (URIs) respond to client requests. In Express.js, routing determines which code executes when a specific URL path is accessed with a particular HTTP method (GET, POST, PUT, DELETE, etc.).

Think of routes as the "address system" of your web application—they direct incoming requests to the appropriate handler functions that process the request and send back a response.

Basic Route Structure

An Express route has the following structure:

javascript
app.METHOD(PATH, HANDLER);

Where:

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

Creating Your First Routes

Let's start with a basic Express application and define some simple routes:

javascript
const express = require('express');
const app = express();
const port = 3000;

// Basic route that responds with text
app.get('/', (req, res) => {
res.send('Welcome to my Express application!');
});

// Route with a parameter
app.get('/users/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`);
});

// Route that serves JSON
app.get('/api/products', (req, res) => {
const products = [
{ id: 1, name: 'Laptop' },
{ id: 2, name: 'Phone' }
];
res.json(products);
});

app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});

When you run this application:

  • Visiting http://localhost:3000/ will display "Welcome to my Express application!"
  • Visiting http://localhost:3000/users/42 will display "User ID: 42"
  • Visiting http://localhost:3000/api/products will return a JSON array of products

HTTP Methods in Express Routes

Express supports all HTTP methods for routing. Let's explore the most common ones:

javascript
// GET method (retrieve data)
app.get('/posts', (req, res) => {
res.send('List of all posts');
});

// POST method (create new data)
app.post('/posts', (req, res) => {
res.send('Creating a new post');
});

// PUT method (update existing data)
app.put('/posts/:id', (req, res) => {
res.send(`Updating post with ID: ${req.params.id}`);
});

// DELETE method (remove data)
app.delete('/posts/:id', (req, res) => {
res.send(`Deleting post with ID: ${req.params.id}`);
});

Route Parameters

Route parameters are named segments in the URL that capture values at their positions. They are defined by prefixing a colon to the parameter name:

javascript
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(`User ID: ${req.params.userId}, Book ID: ${req.params.bookId}`);
});

If you visit /users/34/books/8989, you'll see:

User ID: 34, Book ID: 8989

Route Handlers

You can provide multiple callback functions for a single route. These functions behave like middleware and can be useful for code organization:

javascript
const validateUser = (req, res, next) => {
// Check if user exists in database
const userExists = true; // This would be a real check in a production app

if (userExists) {
// If validation passes, continue to the next handler
next();
} else {
// If validation fails, send an error response
res.status(404).send('User not found');
}
};

app.get('/dashboard/:userId', validateUser, (req, res) => {
res.send(`Welcome to your dashboard, user ${req.params.userId}!`);
});

Route Paths

Express supports various forms of route paths:

  1. String paths:
javascript
app.get('/about', (req, res) => {
res.send('About page');
});
  1. String patterns with wildcards:
javascript
app.get('/files/*.pdf', (req, res) => {
res.send('PDF file requested');
});
  1. Regular expressions:
javascript
// Match paths ending with 'fly' (butterfly, dragonfly, etc.)
app.get(/.*fly$/, (req, res) => {
res.send('Something that flies!');
});

Response Methods

Express provides various methods for sending responses:

javascript
app.get('/responses/demo', (req, res) => {
// Choose one of these response methods:

// Send a simple text response
// res.send('Plain text response');

// Send JSON data
// res.json({ message: 'This is JSON data', success: true });

// Send a specific status code
// res.status(201).send('Resource created');

// Redirect to another URL
// res.redirect('/another-page');

// Render a template (requires template engine setup)
// res.render('index', { title: 'Express' });

// Send a file as download
// res.download('path/to/file.pdf');

// End the response without data
// res.end();
});

Real-World Example: Building a Mini Blog API

Let's put everything together in a more practical example of a simple blog API:

javascript
const express = require('express');
const app = express();
const port = 3000;

// Middleware to parse JSON bodies
app.use(express.json());

// In-memory database (would use a real database in production)
let posts = [
{ id: 1, title: 'Introduction to Express', content: 'Express is a web framework for Node.js' },
{ id: 2, title: 'Route Parameters', content: 'Route parameters are named URL segments' }
];

// GET all posts
app.get('/api/posts', (req, res) => {
res.json(posts);
});

// GET a single post by ID
app.get('/api/posts/:id', (req, res) => {
const post = posts.find(p => p.id === parseInt(req.params.id));

if (!post) {
return res.status(404).json({ error: 'Post not found' });
}

res.json(post);
});

// CREATE a new post
app.post('/api/posts', (req, res) => {
if (!req.body.title || !req.body.content) {
return res.status(400).json({ error: 'Title and content are required' });
}

const newPost = {
id: posts.length + 1,
title: req.body.title,
content: req.body.content
};

posts.push(newPost);
res.status(201).json(newPost);
});

// 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).json({ error: 'Post not found' });
}

if (req.body.title) post.title = req.body.title;
if (req.body.content) 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).json({ error: 'Post not found' });
}

const deletedPost = posts[postIndex];
posts.splice(postIndex, 1);

res.json(deletedPost);
});

app.listen(port, () => {
console.log(`Blog API running on port ${port}`);
});

With this API, you can:

  • Get all blog posts with a GET request to /api/posts
  • Get a specific post with a GET request to /api/posts/1
  • Create a new post with a POST request to /api/posts
  • Update a post with a PUT request to /api/posts/1
  • Delete a post with a DELETE request to /api/posts/1

Route Organization

As your application grows, it's best practice to organize routes into separate modules:

javascript
// routes/posts.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
res.send('All posts');
});

router.get('/:id', (req, res) => {
res.send(`Post ID: ${req.params.id}`);
});

module.exports = router;

// app.js (main file)
const express = require('express');
const app = express();
const postsRoutes = require('./routes/posts');

// Mount the posts router at the /posts path
app.use('/posts', postsRoutes);

app.listen(3000);

With this organization, the paths in the posts router are relative to the /posts path where the router is mounted.

Summary

In this introduction to Express routes, we've learned:

  • How to define basic routes using different HTTP methods
  • How to capture parameters from URL paths
  • How to send different types of responses
  • How to organize routes as your application grows
  • How to build a simple RESTful API

Routing is the foundation of any Express application, allowing you to create clean, maintainable, and intuitive APIs for your web applications.

Practice Exercises

  1. Create a simple Express application with routes for a todo list (get all, get one, create, update, delete)
  2. Build a route that accepts query parameters (e.g., /search?term=express&limit=10)
  3. Create a route that handles file uploads
  4. Implement route validation using middleware functions
  5. Create a nested router structure for a more complex API (e.g., /api/v1/users/:userId/posts/:postId/comments)

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)