
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 aGET
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 withconst 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 theMETHOD
andPATH
. This function always receives two key objects:req
(request) andres
(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 allGET
requests to the root URL (/
). -
app.get('/api/users', ...)
: This handles allGET
requests to/api/users
. We useres.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 thatid
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 thereq.params
object. Important: The value is always a string, so we useparseInt()
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 a404 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 accessreq.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:
-
Install: Search for "Thunder Client" in the VS Code Extensions panel and install it.
-
New Request: Click the Thunder Client icon in your activity bar on the left, then click "New Request".
-
Set Method: Change the dropdown from
GET
toPOST
. -
Enter URL: In the URL field, type
http://localhost:3000/api/users
. -
Add Body: Click the "Body" tab, then the "Json" sub-tab.
-
Enter JSON Data: In the text area, type the following JSON:
{ "name": "New Coder" }
-
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 beundefined
. -
Not Validating Input: Always assume client data is untrustworthy. You must validate
req.params
,req.body
, andreq.query
to prevent unexpected behavior and security vulnerabilities. -
Forgetting
parseInt()
: Remember that values fromreq.params
andreq.query
are strings. UseparseInt()
orparseFloat()
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. Useexpress.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