Skip to main content

Express Query Strings

Query strings are a crucial part of web development that allow clients to send data to servers through URLs. In this tutorial, we'll learn how to work with query strings in Express.js applications.

What are Query Strings?

Query strings are portions of a URL that come after a question mark (?) and contain key-value pairs. They provide a way to send data to the server as part of a GET request.

For example, in the URL https://example.com/search?q=express&category=javascript, the query string is q=express&category=javascript, which contains two key-value pairs:

  • q with value express
  • category with value javascript

Accessing Query Strings in Express

Express makes working with query strings straightforward by parsing them automatically and providing them in the req.query object.

Let's look at a basic example:

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

app.get('/search', (req, res) => {
// Access query parameters from req.query
const query = req.query.q;
const category = req.query.category;

res.send(`You searched for "${query}" in category "${category}"`);
});

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

If a user visits http://localhost:3000/search?q=express&category=javascript, they will see:

You searched for "express" in category "javascript"

Working with Optional Query Parameters

In real-world applications, query parameters are often optional. Let's see how to handle optional parameters:

javascript
app.get('/products', (req, res) => {
const category = req.query.category || 'all';
const minPrice = req.query.minPrice || 0;
const maxPrice = req.query.maxPrice || Infinity;
const sort = req.query.sort || 'default';

res.send({
filters: {
category,
priceRange: { min: minPrice, max: maxPrice },
sortBy: sort
},
message: `Showing ${category} products from $${minPrice} to $${maxPrice} sorted by ${sort}`
});
});

With this route, users can include any combination of parameters:

  • http://localhost:3000/products → Shows all products
  • http://localhost:3000/products?category=electronics → Shows electronics only
  • http://localhost:3000/products?minPrice=50&maxPrice=200 → Shows products between 5050-200
  • http://localhost:3000/products?category=books&sort=price-asc → Shows books sorted by price

Handling Arrays and Complex Values

Arrays in Query Strings

Query strings can contain arrays by repeating the same parameter name:

/filter?color=red&color=blue&color=green

Express parses this automatically into an array:

javascript
app.get('/filter', (req, res) => {
const colors = req.query.color; // Will be an array: ['red', 'blue', 'green']

res.send(`You selected colors: ${colors.join(', ')}`);
});

Parsing Numeric Values

Query parameters are always strings initially. If you need numbers, you'll have to convert them:

javascript
app.get('/calculate', (req, res) => {
// Convert string values to numbers
const x = parseFloat(req.query.x) || 0;
const y = parseFloat(req.query.y) || 0;

const sum = x + y;

res.send(`The sum of ${x} and ${y} is ${sum}`);
});

Practical Examples

Example 1: Building a Search API

Let's create a more realistic search API with pagination:

javascript
const products = [
{ id: 1, name: 'Laptop', category: 'electronics', price: 999 },
{ id: 2, name: 'Headphones', category: 'electronics', price: 199 },
{ id: 3, name: 'JavaScript Book', category: 'books', price: 39 },
{ id: 4, name: 'Hiking Boots', category: 'outdoor', price: 129 },
// ...imagine more products here
];

app.get('/api/products', (req, res) => {
let results = [...products];

// Filter by category
if (req.query.category) {
results = results.filter(product =>
product.category === req.query.category.toLowerCase()
);
}

// Filter by price range
const minPrice = parseFloat(req.query.minPrice) || 0;
const maxPrice = parseFloat(req.query.maxPrice) || Infinity;
results = results.filter(product =>
product.price >= minPrice && product.price <= maxPrice
);

// Implement pagination
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const startIndex = (page - 1) * limit;
const endIndex = page * limit;

const paginatedResults = results.slice(startIndex, endIndex);

res.json({
total: results.length,
page,
limit,
results: paginatedResults
});
});

Example 2: Building a Simple URL Shortener

javascript
// Simple in-memory storage for our shortened URLs
const urlDatabase = {};

// Create a shortened URL
app.get('/api/shorten', (req, res) => {
const longUrl = req.query.url;

if (!longUrl) {
return res.status(400).json({ error: 'URL parameter is required' });
}

// Generate a simple short code (in production, use a better method)
const shortCode = Math.random().toString(36).substring(2, 8);

// Store in our database
urlDatabase[shortCode] = longUrl;

// Return the shortened URL
res.json({
originalUrl: longUrl,
shortUrl: `http://localhost:3000/u/${shortCode}`
});
});

// Redirect short URLs to their destination
app.get('/u/:code', (req, res) => {
const code = req.params.code;
const longUrl = urlDatabase[code];

if (longUrl) {
return res.redirect(longUrl);
}

res.status(404).send('URL not found');
});

Best Practices for Query Strings

  1. Validate and sanitize input: Always validate and sanitize query parameters to prevent security issues.
javascript
// Bad practice - vulnerable to injection
app.get('/users', (req, res) => {
const query = req.query.search;
// Directly using the query parameter without validation
});

// Good practice
app.get('/users', (req, res) => {
const query = req.query.search;

// Validate the query parameter
if (query && typeof query === 'string') {
// Sanitize and use the parameter
const sanitizedQuery = query.replace(/[^a-zA-Z0-9 ]/g, '');
// Now use sanitizedQuery
} else {
return res.status(400).send('Invalid search query');
}
});
  1. Document your API: Make sure to document what query parameters your API endpoints accept.

  2. Use meaningful parameter names: Choose descriptive names that indicate what the parameter does.

  3. Handle defaults gracefully: Provide sensible defaults for optional parameters.

Common Challenges with Query Strings

1. URL Length Limitations

Query strings are part of the URL, and browsers have URL length limitations (typically around 2000 characters). For large data sets, consider using POST requests with a request body instead.

2. Special Characters

Query strings need URL encoding for special characters:

javascript
// Client-side JavaScript to create a URL with encoded query parameters
const search = "Node.js & Express";
const category = "Web Development";

const url = `/search?q=${encodeURIComponent(search)}&category=${encodeURIComponent(category)}`;
// Result: /search?q=Node.js%20%26%20Express&category=Web%20Development

In Express, query parameters are automatically decoded for you in req.query.

Summary

Query strings are a powerful way to pass data to your Express applications through URLs. With Express's built-in parsing, you can easily access query parameters through the req.query object. They're ideal for:

  • Search functionality
  • Filtering data
  • Pagination
  • Sorting
  • Sharing links with specific states

Remember to validate and sanitize user input, provide sensible defaults, and consider URL length limitations when working with query strings.

Additional Resources

Exercises

  1. Create a weather API endpoint that accepts a city query parameter and returns weather information.

  2. Build a movie database API with endpoints that allow filtering by genre, release year, and rating.

  3. Implement a blog API with search functionality that allows searching by title, author, and tags.

  4. Create a product filtering system with multiple filter options (price range, category, brand, etc.) using query parameters.



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