Login

Sign Up

Mastering Routing in Express.js
Daksh Dixit

Posted on Aug 4, 2025 | Backend

Mastering Routing in Express.js

Hey Devs!

Ready to level up your Node.js skills? Now that you have a basic Express server running, it's time to make it truly interactive. If you don't know how to run an express server I recommend reading this blog on Getting Started With Express.
Today, we'll take a deep dive into routing, the mechanism that allows your application to perform different actions based on the URL and method of a request.

Routing is the heart of any web application. It’s the logic that directs traffic, ensuring that a user's request for /about shows them the "About Us" page, while a form submission to /create-post saves their new content. Mastering routing is the key to building powerful and well-structured APIs and web applications.

What are Routes?

At its core, a route is a combination of an HTTP method and a URL path. Think of your server as a large office building and each route as a specific desk or person inside. When a client (like a web browser or a mobile app) sends a request, it's like someone walking into the building with a specific question or task.

The server's job is to look at the request and decide where to send it.

  • HTTP Method: What action do you want to perform? (e.g., GET to retrieve information, POST to submit new information).

  • URL Path: Where in the building are you going? (e.g., /users, /products/5, /settings).

Types of Routes (HTTP Methods)

Express.js allows you to handle all standard HTTP methods. Here are the most common ones you'll use:

  • GET: The most common method. Used to retrieve data from the server. For example, getting a list of all users or viewing a single user's profile. A browser makes a GET request every time you type in a URL and press enter.

  • POST: Used to send new data to the server to create a new resource. For example, submitting a signup form or creating a new blog post.

  • PUT: Used to update an existing resource. For example, editing a user's profile information.

  • DELETE: Used to remove a resource from the server. For example, deleting a user account.

How to Handle Routes in Express

Express provides a simple and intuitive way to define routes using the following structure:

app.METHOD(PATH, HANDLER)

Let's break down each part:

  • app: This is your Express application instance, which you typically create with const app = express();.

  • METHOD: This is a lowercase version of an HTTP verb (e.g., app.get, app.post, app.put, app.delete).

  • PATH: This is the URL path on your server, such as / for the homepage, or /api/users.

  • HANDLER: This is the function that Express executes when the request matches the METHOD and PATH. This function always receives two key objects: req (request) and res (response).

Prerequisites:

Before we start, make sure you have a basic Express project setup with a file like app.js and nodemon running to automatically restart your server.
For reference you can refer to this blog here Getting Started With Express.

Step 1: Handling GET Requests

Let's start with a simple GET route. Open your app.js file and add the following code.

// app.js
const express = require('express');
const app = express();
const port = 3000;

// A simple GET route for the homepage
app.get('/', (req, res) => {
    res.send('Welcome to the Routing Guide!');
});

// A GET route to fetch a list of all users
const users = [
    { id: 1, name: 'Daksh Dixit' },
    { id: 2, name: 'Our Awesome Reader-1' },
    { id: 3, name: 'Ujjwalit' }
];

app.get('/api/users', (req, res) => {
    // The res.json() method sends a JSON response
    res.json(users);
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

Explanation:

  • app.get('/', ...): This handles all GET requests to the root URL (/).

  • app.get('/api/users', ...): This handles all GET requests to /api/users. We use res.json() to automatically convert our JavaScript array into a JSON string and send it to the client.

Now, run your server with nodemon app.js and navigate to http://localhost:3000/api/users in your browser. You should see the JSON data for all the users.

Step 2: Handling Route Parameters

What if you want to get a single user, not the whole list? This is where route parameters come in. They allow you to define dynamic parts of a URL.

Let's add a new GET route to get a user by their ID.

// ... (keep the existing code from above)

// A GET route with a route parameter 'id'
// The colon (:) signifies a dynamic parameter
app.get('/api/users/:id', (req, res) => {
    // The route parameter is available in the req.params object
    // For a request to /api/users/2, req.params will be { id: '2' }
    const user = users.find(u => u.id === parseInt(req.params.id));
    
    // Always handle cases where the resource is not found!
    if (!user) {
        // Send a 404 Not Found status with a helpful message
        return res.status(404).send('The user with the given ID was not found.');
    }
    
    res.json(user);
});
// ... (keep the app.listen part)

Explanation:

  • '/api/users/:id': The colon (:) tells Express that id is a placeholder for a value.

  • req.params.id: Express automatically captures the value from the URL (e.g., 2 from /api/users/2) and stores it as a property on the req.params object. Important: The value is always a string, so we use parseInt() to convert it to a number for our comparison.

  • res.status(404).send(...): This is a crucial best practice. If the user doesn't exist, we send a 404 Not Found status code, which tells the client that the requested resource is not available.

Try it out by visiting http://localhost:3000/api/users/2 and then http://localhost:3000/api/users/99 to see the error message.

Step 3: Handling POST Requests & The Request Body

When a client wants to create a new resource, they use a POST request. The data for the new resource is sent in the request body.

To handle this data, Express needs a special tool called middleware. The express.json() middleware is perfect for this. It parses incoming JSON data and makes it available on the req.body object.

// ... (keep the existing code from above)

// Middleware to parse incoming JSON data
// This must be added before your POST routes
app.use(express.json()); 

// A POST route to create a new user
app.post('/api/users', (req, res) => {
    // 1. Validate the incoming data from the request body
    if (!req.body.name || req.body.name.length < 3) {
        // 400 Bad Request is the correct status code for invalid client input
        return res.status(400).send('Name is required and should be at least 3 characters.');
    }

    // 2. Create the new user object
    const newUser = {
        id: users.length + 1, // Simple way to generate an ID
        name: req.body.name
    };

    // 3. Add the new user to our array (our "database")
    users.push(newUser);

    // 4. Send back the newly created user with a 201 Created status
    res.status(201).json(newUser);
});

// ... (keep the app.listen part)

Explanation:

  • app.use(express.json());: This line is vital. It must be placed at the top of your file, before any routes that need to access req.body.

  • req.body: This is where the data from the client's form submission or JSON payload lives.

  • res.status(201).json(...): 201 Created is the standard status code to tell the client that a new resource was successfully created.

Step 4: Working with a REST Client

You can't test a POST route by simply typing a URL into a browser. You need a tool that can send HTTP requests with a specific method and a request body. This is where a REST client comes in.

We recommend using Thunder Client, a lightweight and excellent extension for VS Code.

How to Test Your POST Route with Thunder Client:

  1. Install: Search for "Thunder Client" in the VS Code Extensions panel and install it.

  2. New Request: Click the Thunder Client icon in your activity bar on the left, then click "New Request".

  3. Set Method: Change the dropdown from GET to POST.

  4. Enter URL: In the URL field, type http://localhost:3000/api/users.

  5. Add Body: Click the "Body" tab, then the "Json" sub-tab.

  6. Enter JSON Data: In the text area, type the following JSON:

    {
        "name": "New Coder"
    }
    
  7. Send Request: Click the "Send" button.

You should see the response from your server with the new user object and a 201 Created status! Now, if you go to http://localhost:3000/api/users in your browser, you'll see your new user in the list.

Step 5: Working with Query Strings

Query strings are used to filter, sort, or paginate data. They appear at the end of a URL after a question mark ?. For example: /api/posts?sortBy=date&limit=10.

Express automatically parses the query string and puts the key-value pairs into the req.query object.

Add this simple route to your app.js file:

// ... (keep the existing code from above)

// A GET route to demonstrate query strings
app.get('/api/posts', (req, res) => {
    // For a URL like /api/posts?sortBy=views&limit=5,
    // req.query will be { sortBy: 'views', limit: '5' }
    res.send(req.query);
});

// ... (keep the app.listen part)

Restart your server and visit http://localhost:3000/api/posts?sortBy=views&filter=popular in your browser. You will see the JSON response: { "sortBy": "views", "filter": "popular" }.

Step 6: A Quick Look at PUT and DELETE

Now that you understand route parameters and the request body, PUT and DELETE requests will seem very familiar. They combine these two concepts to update or remove an existing resource.

Let's add routes to update and delete a user by ID.

// ... (keep the existing code from above)

// PUT - Update an existing user
app.put('/api/users/:id', (req, res) => {
    // 1. Find the user with the given ID
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) return res.status(404).send('User not found.');

    // 2. Validate the incoming data
    if (!req.body.name || req.body.name.length < 3) {
        return res.status(400).send('Name is required and should be at least 3 characters.');
    }

    // 3. Update the user's name
    user.name = req.body.name;
    
    // 4. Send back the updated user
    res.json(user);
});

// DELETE - Remove a user
app.delete('/api/users/:id', (req, res) => {
    // 1. Find the user with the given ID
    const user = users.find(u => u.id === parseInt(req.params.id));
    if (!user) return res.status(404).send('User not found.');

    // 2. Find the index of the user and remove them from the array
    const index = users.indexOf(user);
    users.splice(index, 1);

    // 3. Send back the deleted user to confirm the action
    res.json(user);
});
// ... (keep the app.listen part)

You can test these routes using a REST client just like you did with the POST route.

Common Mistakes & Additional Tips

Common Mistakes:

  • Forgetting app.use(express.json()): This is a very common beginner mistake. Without this middleware, req.body will always be undefined.

  • Not Validating Input: Always assume client data is untrustworthy. You must validate req.params, req.body, and req.query to prevent unexpected behavior and security vulnerabilities.

  • Forgetting parseInt(): Remember that values from req.params and req.query are strings. Use parseInt() or parseFloat() when you need to perform numerical comparisons or calculations.

Additional Tips for Better Practice:

  • Use Correct HTTP Status Codes: Sending the right status code (200 OK, 201 Created, 400 Bad Request, 404 Not Found) makes your API predictable and easier for other developers to use.

  • Keep Route Handlers Lean: Your handler function should be simple. If the logic gets complicated, move it to a separate function or module and call it from your route handler. This keeps your code organized and easy to read.

  • Use express.Router for Organization: As your application grows, defining all your routes in one file becomes messy. Use express.Router to group related routes into separate files (e.g., users.js, posts.js) for a cleaner architecture.

Conclusion

You've now mastered the fundamentals of routing in Express.js! You can handle different HTTP methods, capture dynamic values from the URL with route parameters, parse request bodies for creating and updating data, and use query strings for filtering. These are the essential building blocks for creating any REST API or web application backend.

Have fun coding with Express!

Enjoy the content here?
Sign up on our platform or join our WhatsApp channel here to get more hands-on guides like this, delivered regularly.

See you in the next blog. Until then, keep practicing and happy learning!

4 Reactions

0 Bookmarks

Read next

Daksh Dixit

Daksh Dixit

Dec 29, 24

14 min read

|

Decoding the Web: A Beginner's Guide

Daksh Dixit

Daksh Dixit

Jan 5, 25

10 min read

|

Introduction to HTML, CSS, and JavaScript