Chapter 3 of 13
~11 minRoute Parameters & Query Strings
Most real routes need more than a fixed path - they need to accept an identifier, a filter, or an optional setting from the URL itself. Express gives you two distinct tools for this: route parameters via req.params, and query strings via req.query.
req.params - Values Embedded in the Path
Route parameters are the named, colon-prefixed segments of a route path (like /users/:userId/orders/:orderId), and Express collects every matched segment into the req.params object, keyed by name. Parameters are always strings, even when the URL segment looks numeric, so code that expects a number needs to convert it explicitly.
app.get('/users/:userId/orders/:orderId', (req, res) => { const { userId, orderId } = req.params; res.json({ userId, orderId, userIdIsString: typeof userId === 'string', }); }); // GET /users/7/orders/99 // -> { "userId": "7", "orderId": "99", "userIdIsString": true }
req.query - Values After the Question Mark
Everything after the ? in a URL is the query string, and Express parses it automatically into the req.query object without any extra setup. Query values are meant for optional filters, sorting, and pagination rather than identifying a specific resource - that is what route parameters are for.
app.get('/products', (req, res) => { const { category, sort, page } = req.query; res.json({ category: category || 'all', sort: sort || 'newest', page: Number(page) || 1, }); }); // GET /products?category=books&sort=price&page=2 // -> { "category": "books", "sort": "price", "page": 2 }
Optional Route Parameters
Appending a ? after a parameter name (:format?) makes that path segment optional, so the same route handler matches both with and without it. When the optional segment is missing, its key still exists on req.params but with a value of undefined, so handlers should check for that before relying on it.
app.get('/reports/:year/:month?', (req, res) => { const { year, month } = req.params; res.json({ year, month: month || 'all months' }); }); // GET /reports/2024 -> { "year": "2024", "month": "all months" } // GET /reports/2024/06 -> { "year": "2024", "month": "06" }
Params vs Query - Choosing the Right One
A useful rule of thumb: if a value identifies which resource you are talking about (a user ID, a post slug), it belongs in the path as a route parameter; if it modifies how a collection of resources is returned (filtering, sorting, pagination, searching), it belongs in the query string. Mixing these up tends to produce awkward, hard-to-cache URLs, like putting a page number in the path or an entity ID in the query string.
Coding challenge
Write a GET route /articles/:id that also accepts optional ?fields=title,author query parameters, returning the id, and an array of the requested field names split from the comma-separated query value (or an empty array if not provided).
// Write your solution here
Answer every question below to mark this chapter as complete.
Quiz Yourself
Score: 0/41. Where does Express place the value matched by a route parameter like :id?
2. What type are values on req.params, even if the URL segment is numeric-looking?
3. Which is the more appropriate way to express "give me page 2 of the product list, sorted by price"?
4. In the route path /reports/:year/:month?, what happens on a request to /reports/2024 with no month segment?