Chapter 2.3☕ 16 min read

Route Parameters & Query Strings — Order ID Dhoondo

URLs can carry data through route parameters (/biryani/2) and query strings (/biryani?spice=High). Learn how to read both in Express.

01URL Parameters — Biryani ID Se Dhoondo

Route parameters are named segments in the URL that capture dynamic values. Think of them like Swiggy order IDs — each order has a unique number, and you use that number to look up the order.

Syntax: /biryani/:id — the colon (:) tells Express to capture whatever value is at that position.

import express from 'express';
const app = express();

app.use(express.json());

let biryaniMenu = [
  { id: 1, name: 'Chicken Biryani', price: 250, spice: 'Medium' },
  { id: 2, name: 'Mutton Biryani', price: 350, spice: 'High' },
  { id: 3, name: 'Veg Biryani', price: 200, spice: 'Low' }
];

// GET /biryani/2 — fetch biryani with id = 2
app.get('/biryani/:id', (req, res) => {
  const id = parseInt(req.params.id);  // Convert string to number!
  const biryani = biryaniMenu.find(item => item.id === id);

  if (!biryani) {
    return res.status(404).json({
      success: false,
      message: 'Biryani not found! Yeh ID exist nahi karti bhai!'
    });
  }

  res.json({ success: true, data: biryani });
});

app.listen(3000);

Testing:

  • GET /biryani/1 → Returns Chicken Biryani
  • GET /biryani/2 → Returns Mutton Biryani
  • GET /biryani/99 → Returns 404 (not found)

Important: req.params.id is always a string — even if the URL has a number! Use parseInt() or Number() to convert before comparing with numeric IDs.

02Query Strings — Spice Level Filter

Query strings come after the ? in the URL and are used for filtering, sorting, pagination — not for identifying specific resources.

Syntax: /biryani?spice=High&sort=price

Query strings are key-value pairs separated by &. In Express, they're available at req.query as an object.

import express from 'express';
const app = express();

let biryaniMenu = [
  { id: 1, name: 'Chicken Biryani', price: 250, spice: 'Medium' },
  { id: 2, name: 'Mutton Biryani', price: 350, spice: 'High' },
  { id: 3, name: 'Veg Biryani', price: 200, spice: 'Low' },
  { id: 4, name: 'Prawn Biryani', price: 400, spice: 'High' }
];

// GET /biryani?spice=High — filter by spice level
app.get('/biryani', (req, res) => {
  let result = biryaniMenu;

  // Filter by spice level
  if (req.query.spice) {
    result = result.filter(item =>
      item.spice.toLowerCase() === req.query.spice.toLowerCase()
    );
  }

  // Filter by max price
  if (req.query.maxPrice) {
    result = result.filter(item =>
      item.price <= parseInt(req.query.maxPrice)
    );
  }

  res.json({
    success: true,
    count: result.length,
    filters: {
      spice: req.query.spice || 'all',
      maxPrice: req.query.maxPrice || 'none'
    },
    data: result
  });
});

app.listen(3000);

Testing:

  • GET /biryani?spice=High → Returns only High spice biryanis
  • GET /biryani?maxPrice=250 → Returns biryanis 250 or less
  • GET /biryani?spice=High&maxPrice=350 → Combined filters!

Query strings are optional — the route still works without them (req.query is just an empty object).

03req.params — Route Se Data Kaise Nikalein

req.params is an object containing all route parameters defined in the URL pattern. Each colon-prefixed segment becomes a key in this object.

How Express parses params:

// Route pattern:  /biryani/:id
// Actual URL:     /biryani/42
// req.params:     { id: '42' }

// Multiple params:  /restaurant/:restId/menu/:itemId
// Actual URL:       /restaurant/5/menu/12
// req.params:       { restId: '5', itemId: '12' }

Using params in a route:

app.get('/biryani/:id', (req, res) => {
  // req.params.id is a string — convert to number!
  const id = Number(req.params.id);

  // Find the item
  const item = menu.find(b => b.id === id);

  if (!item) {
    return res.status(404).json({ error: 'Not found' });
  }

  res.json({ data: item });
});

Common mistakes:

MistakeWrongRight
Forgetting parseIntitem.id === req.params.iditem.id === parseInt(req.params.id)
Wrong param nameURL: /biryani/:id, code: req.params.biryaniIdreq.params.id matches :id
Missing 404Send empty response when not foundReturn res.status(404).json(...)

Param name rule: The name after the colon in the route pattern MUST match the key in req.params. If your route is /biryani/:biryaniId, use req.params.biryaniId.

04req.query — Filter aur Sort Kaise Karein

req.query is an object containing all query string parameters from the URL. Express automatically parses the query string for you — no manual parsing needed!

How URLs break down:

Full URL:    http://localhost:3000/biryani?spice=High&sort=price:asc
                |_____________|  |_____|  |________________________|
                    Base URL       Path        Query String

Query string:  spice=High&sort=price:asc
                   |     |      |       |
                   key   val    key     val

req.query:     { spice: 'High', sort: 'price:asc' }

Practical example — filtering and sorting:

app.get('/biryani', (req, res) => {
  let result = [...biryaniMenu];

  // Filter by spice
  if (req.query.spice) {
    result = result.filter(b =>
      b.spice.toLowerCase() === req.query.spice.toLowerCase()
    );
  }

  // Sort by price
  if (req.query.sort === 'asc') {
    result.sort((a, b) => a.price - b.price);
  } else if (req.query.sort === 'desc') {
    result.sort((a, b) => b.price - a.price);
  }

  res.json({ count: result.length, data: result });
});

Testing query combinations:

curl "http://localhost:3000/biryani?spice=High&sort=asc"

Note: Query strings are always strings. If you expect a number, use parseInt() or parseFloat(). Boolean values come as strings ('true', 'false').

05Combined — Params + Query Ek Saath

Route params and query strings often work together. Params identify which resource, queries control how to present it.

Combined example — get one biryani with optional fields:

app.get('/biryani/:id', (req, res) => {
  const id = Number(req.params.id);
  const biryani = biryaniMenu.find(b => b.id === id);

  if (!biryani) {
    return res.status(404).json({ error: 'Not found' });
  }

  // Optional: ?include=recipe adds extra data
  if (req.query.include === 'recipe') {
    return res.json({
      ...biryani,
      recipe: 'Basmati rice, chicken, spices, saffron, ghee...'
    });
  }

  res.json({ data: biryani });
});

// Example: GET /biryani/1?include=recipe

Real Swiggy-like example — paginated menu with filters:

// GET /restaurant/5/menu?category=Biryani&page=1&limit=10
app.get('/restaurant/:restId/menu', (req, res) => {
  const restId = Number(req.params.restId);
  const page = Number(req.query.page) || 1;
  const limit = Number(req.query.limit) || 10;
  const category = req.query.category;

  // Find restaurant
  const restaurant = restaurants.find(r => r.id === restId);
  if (!restaurant) {
    return res.status(404).json({ error: 'Restaurant not found' });
  }

  // Filter menu
  let items = restaurant.menu;
  if (category) {
    items = items.filter(item =>
      item.category.toLowerCase() === category.toLowerCase()
    );
  }

  // Paginate
  const start = (page - 1) * limit;
  const paginatedItems = items.slice(start, start + limit);

  res.json({
    restaurant: restaurant.name,
    page,
    totalItems: items.length,
    totalPages: Math.ceil(items.length / limit),
    data: paginatedItems
  });
});

// Example: GET /restaurant/5/menu?category=Biryani&page=1&limit=10

This pattern — params for resource identification + queries for filtering/pagination — is standard in all production REST APIs, including Swiggy's.

Key Takeaways

  • ✅ Route params (/biryani/:id) capture dynamic URL segments — req.params.id gives the value.
  • ✅ req.params values are ALWAYS strings — use parseInt() or Number() to convert.
  • ✅ Query strings (/biryani?spice=High) are for filtering/pagination — req.query.spice gives the value.
  • ✅ Query strings are optional — req.query is {} if none provided.
  • ✅ The param name in the route (:id) must exactly match req.params.id.
  • ✅ Always handle 404 when a resource with the given ID is not found.
  • ✅ Combine params (identify resource) + query (filter/present) for full REST APIs.
Course Search
Search across all chapters & stages
📖

Search the course

Type any topic — branching, stash, rebase, hooks — and jump straight to that chapter.

merge branchesgit stashundo commitrebase