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 !❤️