Working with Route Parameters
1. Defining URL Parameters
Path Example URL Captures
/users/:id/users/42 id="42"
/u/:id([0-9]+)/u/42 (numeric only) id="42"
/files/:name.:ext/files/photo.jpg name, ext
/posts/:slug-:id/posts/hello-42 slug, id
2. Accessing Parameters
Example: Reading params
app. get ( "/users/:id" , ( req , res ) => {
const id = req.params.id; // string
const numericId = Number (id); // coerce
res. json ({ id: numericId });
});
Property Type
req.paramsObject (always strings)
req.params.idString
3. Using Multiple Parameters
Example: Nested resources
app. get ( "/categories/:cat/products/:id" , ( req , res ) => {
const { cat , id } = req.params;
res. json ({ category: cat, productId: id });
});
Pattern Result
/:a/:bTwo separate path segments
/:a-:bSame segment, hyphen separator
4. Validating Parameters
Example: Inline guard + express-validator
import { param, validationResult } from "express-validator" ;
app. get ( "/users/:id" ,
param ( "id" ). isUUID (). withMessage ( "Invalid UUID" ),
( req , res ) => {
const errors = validationResult (req);
if ( ! errors. isEmpty ()) return res. status ( 400 ). json ({ errors: errors. array () });
res. json ({ id: req.params.id });
}
);
Strategy Library
Regex in path Built-in (:id(\\d+))
Validator middleware express-validator, zod
Custom guard Plain function before handler
5. Making Parameters Optional
Example: Optional segment
// Express 4
app. get ( "/users/:id?" , ( req , res ) => {
if (req.params.id) return res. json ( getUser (req.params.id));
res. json ( listUsers ());
});
// Express 5 — optional groups via {}
app. get ( "/users{/:id}" , handler);
Syntax Express 4 Express 5
Optional :id?{:id}
Wildcard *{*splat}
6. Using param() Middleware
Example: Centralized lookup
app. param ( "userId" , async ( req , res , next , id ) => {
const user = await db.users. findById (id);
if ( ! user) return res. sendStatus ( 404 );
req.user = user;
next ();
});
app. get ( "/users/:userId" , ( req , res ) => res. json (req.user));
app. put ( "/users/:userId" , ( req , res ) => updateUser (req.user, req.body));
Behavior Detail
One per request Cached even if param appears in multiple routes
Per-router Use router.param() for scoped lookups
7. Pre-processing Parameters
Example: Coerce + normalize
app. param ( "id" , ( req , res , next , raw ) => {
const id = Number (raw);
if ( ! Number. isInteger (id) || id <= 0 ) return res. status ( 400 ). json ({ error: "Invalid id" });
req.id = id; // attach typed value
next ();
});
8. Converting Parameter Types
Target Conversion
Integer parseInt(p, 10) or Number(p)
Float parseFloat(p)
Boolean p === "true"
Date new Date(p) + isNaN() check
UUID Validate against regex
Array p.split(",")
9. Handling Invalid Parameters
Example: 400 vs 404
app. get ( "/users/:id" , async ( req , res ) => {
const id = Number (req.params.id);
if ( ! Number. isInteger (id)) return res. status ( 400 ). json ({ error: "id must be integer" });
const user = await db.users. findById (id);
if ( ! user) return res. status ( 404 ). json ({ error: "User not found" });
res. json (user);
});
Status When
400 Bad Request Param fails validation (wrong type/format)
404 Not Found Valid format but resource missing
422 Unprocessable Semantic validation failure
10. Using Wildcard Parameters
Example: Catch-all
// Express 4
app. get ( "/files/*" , ( req , res ) => {
const path = req.params[ 0 ]; // anything after /files/
res. sendFile (path, { root: "uploads" });
});
// Express 5 named wildcard
app. get ( "/files/{*splat}" , ( req , res ) => {
const segments = req.params.splat; // array
res. json ({ segments });
});
Syntax Captured As
* (Express 4)req.params[0] (string)
{*splat} (Express 5)req.params.splat (array)
{*splat}?Optional wildcard
Warning: Always sanitize wildcard params used in file paths to prevent directory traversal (../).