In Express.js, handling incoming data from the client is a fundamental aspect of building a web application. Two common ways to pass data to the server via HTTP requests are Query Parameters and Route Parameters.
Query Parameters: These are part of the URL and typically appear after the question mark (?). They are often used to filter, sort, or paginate data.
Route Parameters: These are placeholders in the URL path that are used to capture dynamic values. They are useful for routes that involve specific resources, such as a user profile or a product detail page.
In this chapter, we’ll explore these concepts in detail, understand their use cases, and learn how to implement them in Express.js.
Query parameters are key-value pairs that appear at the end of a URL, following a question mark (?). They are typically used to send non-sensitive data to the server, such as filters, search queries, pagination information, or sorting options.
https://example.com/search?query=express&limit=10&page=2
query=express: Represents the search query.limit=10: Limits the number of results to 10.page=2: Specifies that the results should start from the second page.In Express.js, you can access query parameters using the req.query object, which is automatically populated by Express.
Let’s create a simple Express application that handles a search request and returns the query parameters sent by the client.
app.js
const express = require('express');
const app = express();
const port = 3000;
app.get('/search', (req, res) => {
const query = req.query.query || 'No query';
const limit = req.query.limit || 'No limit specified';
const page = req.query.page || 'No page specified';
res.send(`Search Query: ${query}, Limit: ${limit}, Page: ${page}`);
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
query parameter from the URL.limit parameter.page parameter.If you access the URL http://localhost:3000/search?query=express&limit=10&page=2, the server will respond with:
Search Query: express, Limit: 10, Page: 2
Express.js automatically parses multiple query parameters and makes them available as an object. Let’s modify our example to handle more complex search functionality with additional parameters.
app.js
app.get('/search', (req, res) => {
const { query, limit, page, sortBy, order } = req.query;
res.json({
searchQuery: query || 'No query',
limit: limit || 'No limit specified',
page: page || 'No page specified',
sortBy: sortBy || 'No sort specified',
order: order || 'No order specified',
});
});
req.query.Accessing http://localhost:3000/search?query=node&limit=5&page=1&sortBy=name&order=asc will produce the following JSON response:
{
"searchQuery": "node",
"limit": "5",
"page": "1",
"sortBy": "name",
"order": "asc"
}
It’s important to validate and sanitize query parameters, especially if they are used directly in database queries or other sensitive operations. This can help prevent SQL injection attacks or other malicious activities.
Let’s enhance the previous example by adding validation to ensure limit and page are positive integers.
app.js
app.get('/search', (req, res) => {
let { limit, page } = req.query;
limit = parseInt(limit, 10);
page = parseInt(page, 10);
if (isNaN(limit) || limit <= 0) {
return res.status(400).send('Invalid limit value. It should be a positive integer.');
}
if (isNaN(page) || page <= 0) {
return res.status(400).send('Invalid page value. It should be a positive integer.');
}
res.send(`Limit: ${limit}, Page: ${page}`);
});
limit and page parameters to integers.NaN (Not a Number).Accessing http://localhost:3000/search?limit=-5&page=2 will result in:
Invalid limit value. It should be a positive integer.
Route parameters are dynamic segments of the URL path that are defined by placeholders in the route. These placeholders are defined by a colon (:) followed by a name, which is used to capture and access the data in your application.
https://example.com/users/123
123 is a route parameter that could represent a user ID.Route parameters are accessed using the req.params object in Express.js. They are typically used for routes that require specific resource identification, such as fetching a user profile, editing a blog post, or accessing a product page.
Let’s create an Express application that handles user profiles by their IDs.
app.js
app.get('/users/:userId', (req, res) => {
const userId = req.params.userId;
res.send(`User ID: ${userId}`);
});
userId.userId from the URL.Accessing http://localhost:3000/users/123 will respond with:
User ID: 123
You can define multiple route parameters in a single route. For instance, you might want to access both a user ID and a post ID.
app.js
app.get('/users/:userId/posts/:postId', (req, res) => {
const userId = req.params.userId;
const postId = req.params.postId;
res.send(`User ID: ${userId}, Post ID: ${postId}`);
});
/users/:userId/posts/:postId/ : Defines two route parameters, userId and postId.
userId from the URL.postId from the URL.
User ID: 123, Post ID: 456
Output: Accessing http://localhost:3000/users/123/posts/456 will respond with
Express.js allows you to define optional route parameters by appending a question mark (?) to the parameter name.
Let’s modify our example to make the postId optional.
app.js
app.get('/users/:userId/posts/:postId?', (req, res) => {
const userId = req.params.userId;
const postId = req.params.postId || 'No post ID provided';
res.send(`User ID: ${userId}, Post ID: ${postId}`);
});
postId optional.postId is not provided, the response will indicate that no post ID was provided.Accessing http://localhost:3000/users/123/posts/456 will respond with:
User ID: 123, Post ID: 456
Accessing: http://localhost:3000/users/123/posts will respond with:
User ID: 123, Post ID: No post ID provided
You can use both query parameters and route parameters in the same route to handle more complex scenarios.
Let’s create an API endpoint that fetches a specific user’s post and allows optional filtering based on a query parameter.
app.js
app.get('/users/:userId/posts/:postId', (req, res) => {
const userId = req.params.userId;
const postId = req.params.postId;
const filter = req.query.filter || 'No filter applied';
res.json({
userId,
postId,
filter,
});
});
filter to apply a filter to the post.Accessing http://localhost:3000/users/123/posts/456?filter=recent will return:
{
"userId": "123",
"postId": "456",
"filter": "recent"
}

It’s essential to handle cases where route parameters or query parameters are missing or invalid. Proper error handling ensures that your API behaves predictably and provides meaningful error messages to the client.
app.js
app.get('/users/:userId/posts/:postId', (req, res) => {
const userId = req.params.userId;
const postId = req.params.postId;
if (!userId || !postId) {
return res.status(400).json({ error: 'User ID and Post ID are required' });
}
const filter = req.query.filter;
if (filter && !['recent', 'popular'].includes(filter)) {
return res.status(400).json({ error: 'Invalid filter. Allowed values: recent, popular' });
}
res.json({
userId,
postId,
filter: filter || 'No filter applied',
});
});
userId and postId are provided. If not, it returns a 400 error.filter query parameter, ensuring it’s one of the allowed values (recent or popular). If not, it returns a 400 error.Accessing http://localhost:3000/users/123/posts/456?filter=unknown will result in:
{
"error": "Invalid filter. Allowed values: recent, popular"
}
In this chapter, we explored the concepts of Query Parameters and Route Parameters in Express.js. Understanding how to use these parameters effectively is crucial for building robust and scalable web applications.Happy coding !❤️
