Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Route parameters and the query string

An address often carries data: the post number in /posts/2 or the page number in /posts?page=3. The first is called a route parameter, the second a query string. Express parses both and puts the result into the request object.

Blog data

There is no database yet, so posts are stored in an array. Create the file src/data/posts.js:

// src/data/posts.js
export const posts = [
  { id: 1, title: 'Meet Express', body: 'Express is a web framework for Node.js.' },
  { id: 2, title: 'Routes', body: 'A route connects an address to a function.' },
];

A route parameter

A part of the address after a colon becomes a parameter. Its value is in req.params:

// src/app.js
import { posts } from './data/posts.js';
 
app.get('/posts/:id', (req, res) => {
  const id = Number(req.params.id);
  const post = posts.find((item) => item.id === id);
 
  if (!post) {
    return res.status(404).send('Post not found');
  }
 
  res.send(post.title);
});

At /posts/2 the page shows "Routes", and at /posts/99 — "Post not found". A parameter value is always a string, so it is converted to a number before comparing.

Several parameters

An address can have several parameters:

// src/app.js
app.get('/posts/:postId/comments/:commentId', (req, res) => {
  const { postId, commentId } = req.params;
  res.send(`Comment ${commentId} on post ${postId}`);
});

/posts/2/comments/5 returns "Comment 5 on post 2".

An optional parameter

In Express 5 an optional part of the address is wrapped in curly braces:

// src/app.js
app.get('/archive{/:year}', (req, res) => {
  const year = req.params.year ?? 'all years';
  res.send(`Archive: ${year}`);
});

The route matches both /archive and /archive/2025.

The query string

Everything after ? in the address is parsed by Express into the req.query object. These values do not need a separate route:

// src/app.js
app.get('/posts', (req, res) => {
  const search = req.query.search ?? '';
  const found = posts.filter((post) => post.title.includes(search));
 
  res.send(found.map((post) => post.title).join(', '));
});

/posts?search=Rou shows only "Routes", and /posts without a query string shows all posts.

Which to choose

WayWhen it fitsExample
Route parameterThe address of a specific record/posts/2
Query stringSearch, filters, sorting, pages/posts?page=2&sort=new

Links are built as plain strings: <a href="/posts/2"> or <a href="/posts?page=2"> in HTML.

Common mistake

Values from req.params and req.query are strings, not numbers. The comparison post.id === req.params.id is always false, because 1 === '1' gives false. Convert the value with Number() and check the result: Number('abc') gives NaN, and there is no point searching for such a post — answer 404 right away.

Thanks for reading!

Donate to the site — we work hard for you.