HTTP Routing · Notes
HTTP Routing — Notes
Static · Dynamic · Path params · Query params · Nested · Versioning · Catch-all
Video walkthrough → exam-ready notes
Contents
1. What is Routing? (The "where" of a request)
2. How Method + Route → Handler Mapping Works
3. Static Routes
4. Dynamic Routes & Path Parameters
5. Query Parameters
5.1 Path params vs Query params
5.2 Pagination + filter + sort patterns
6. Nested Routes — Semantic Layering
7. Route Versioning & Deprecation
8. Catch-All Routes (404 handler)
9. Routing Cheat-Sheet
1. What is Routing?
Earlier we learned HTTP methods — they express the WHAT (your intent: fetch, create, update, delete). Routing
expresses the WHERE — which resource on the server you want to perform that action on.
Part of a request Question it answers Example
HTTP method What do you want to do? GET, POST, PATCH, PUT, DELETE
Route Where do you want to do it? /api/users, /api/books/42
EXAM One-liner: Routing is mapping URL patterns (combined with the HTTP method) to
a specific handler function on the server.
STORY Concrete example: A client sends GET /api/users. The intent is "fetch data"
(GET), and the target resource is "users". The server matches that combination to
the get-all-users handler, which runs auth, queries the DB, and returns the array
of users.
2. How (Method + Route) Maps to a Handler
The server keeps an internal table of route definitions. For each incoming request, it concatenates the method
and the path and looks up the matching handler. Method + path together form a unique key — same path with
different methods routes to different handlers.
JS
Page 1 of 8
HTTP Routing · Notes
[Link]('/api/books', getAllBooksHandler); // GET /api/books
[Link]('/api/books', createBookHandler); // POST /api/books
← same path, different method
[Link]('/api/books/:id', getBookByIdHandler); // GET
/api/books/42
[Link]('/api/books/:id', updateBookHandler); // PATCH
/api/books/42
[Link]('/api/books/:id', deleteBookHandler); // DELETE
/api/books/42
NOTE Method + path = unique key. GET /api/books and POST /api/books share a path
but never conflict — the method disambiguates them. This is fundamental to
RESTful design.
3. Static Routes
A static route has no variable parts — the path is a constant string that never changes between requests.
HTTP
GET /api/books → list all books
POST /api/books → create a book
GET /api/health → liveness probe
GET /api/auth/login → login endpoint
• Always the same string, always the same handler.
• Easiest to reason about — no parsing of URL segments needed.
• Used for collection endpoints (e.g. list of users), action endpoints (e.g. login), and status endpoints
(e.g. /health).
4. Dynamic Routes & Path Parameters
Dynamic routes contain a placeholder segment — a slot that captures whatever value the client passes in that
position.
Convention
HTTP
# Route pattern
GET /api/users/:id
# Actual requests
GET /api/users/123 → :id = "123"
GET /api/users/abc-456 → :id = "abc-456"
GET /api/users/suryanshi → :id = "suryanshi"
Page 2 of 8
HTTP Routing · Notes
NOTE The :id convention is universal — Express, FastAPI, Fastify, Spring, Gin, Rails,
Laravel all use it. Some use {id} instead (FastAPI, Java Spring), but the idea is
identical.
What the server actually does
• Splits the incoming URL on "/" — gets ["api", "users", "123"].
• Matches against the pattern ["api", "users", ":id"].
• Captures "123" into a params object: { id: "123" }.
• Calls the handler — handler reads [Link] and uses it to query the DB.
WARNING Type gotcha: Path parameters are ALWAYS strings, even if they look like
numbers. "123" is a string. Cast it explicitly in your handler if your DB expects an
integer ID. Same for booleans, UUIDs, etc.
Why this is "RESTful" and human-readable
GET /api/users/123/posts/456 reads almost like English: "get the post with id 456 belonging to the user
with id 123." That readability is the whole point of REST.
5. Query Parameters
Query params are key-value pairs appended to the URL after a "?". Multiple params are separated by "&".
HTTP
GET /api/search?query=some+value
GET /api/books?page=2&limit=20&sort_by=title&order=desc
GET /api/users?role=admin&active=true
Why we need them — what about path params or body?
Option Why it doesn’t fit for filters/sort/pagination
Request body GET requests don’t conventionally carry a body — most servers/proxies ignore
it.
Path params Path params are for identifying a resource (semantic identity). Stuffing
filter/sort/page values there breaks RESTful semantics and bloats route
patterns.
Query params Designed exactly for this — non-identifying metadata that modifies how the
resource is returned.
Page 3 of 8
HTTP Routing · Notes
5.1 Path params vs Query params — the line
Path parameter Query parameter
Identifies WHICH resource Filters / sorts / paginates the response
/users/:id → which user ?role=admin → which subset of users
Part of the resource URI; always required Optional; defaults applied if missing
Changes the resource being addressed Changes how the same resource is presented
Indexed by REST routing tables Read by the handler as needed
EXAM Rule of thumb: If the value changes what you’re fetching → path param. If it
changes how you’re fetching → query param.
5.2 The canonical pagination pattern
JSON
# Default request — server applies its own defaults
GET /api/books
→ returns page 1 with default limit (e.g. 20)
# Client controls pagination + sort + filter
GET /api/books?page=2&limit=20&sort_by=title&order=desc&author=tolkien
# Typical response shape
{
"data": [ /* 20 books */ ],
"meta": {
"total": 100,
"current_page": 2,
"total_pages": 5,
"limit": 20
}
}
TIP Standard query-param names: page, limit (or per_page), sort_by, order
(asc/desc), q (search). Stick to common names — frontend devs and API
consumers expect them.
URL encoding
Special characters in query values must be URL-encoded. Spaces → + or %20. & → %26. Most HTTP clients do
this automatically.
HTTP
Page 4 of 8
HTTP Routing · Notes
?query=some value ← invalid (raw space)
?query=some+value ← OK
?query=some%20value ← OK
6. Nested Routes — Semantic Layering
Nested routes layer multiple resources together to express ownership or context. Each segment narrows the
meaning.
HTTP
GET /api/users → all users
GET /api/users/123 → user 123
GET /api/users/123/posts → all posts by user 123
GET /api/users/123/posts/456 → post 456 by user 123
GET /api/users/123/posts/456/comments → comments on that post
What each stop returns
Route Returns
/api/users List of users (collection)
/api/users/123 Single user object
/api/users/123/posts List of posts owned by user 123 (filtered collection)
/api/users/123/posts/456 Single post (scoped to that user)
NOTE Why nest at all? It makes the relationship visible in the URL.
/users/123/posts is clearer than /posts?user_id=123 — and the server
can enforce that 456 actually belongs to 123 (otherwise → 404 or 403).
WARNING Don’t over-nest. 3 levels deep is usually the practical ceiling.
/api/users/:uid/projects/:pid/tasks/:tid/comments/:cid/repli
es/:rid is painful to type, painful to validate, painful to debug. If you find
yourself going deeper, query params or sub-endpoints are usually cleaner.
7. Route Versioning & Deprecation
When the response shape of an endpoint needs a breaking change, you DON’T edit the existing route — you
publish a new version alongside it.
HTTP
# v1 response shape
GET /api/v1/products
Page 5 of 8
HTTP Routing · Notes
{ "data": [ { "id": 1, "name": "X", "price": 10 } ] }
# v2 response shape — breaking change (name → title)
GET /api/v2/products
{ "data": [ { "id": 1, "title": "X", "price": 10 } ] }
Why versioning, not replacing?
Without versioning With versioning
Change the existing route → every client breaks Old route keeps working; clients migrate on their
immediately schedule
Mobile apps in the wild break on next release Mobile apps continue using v1 until users update
No clear migration window Deprecation window — announce, give time, then
remove
Typical lifecycle
• Release v2 alongside v1. Both work.
• Mark v1 as deprecated in docs. Add a Sunset header or Deprecation header to v1 responses.
• Give clients a clear migration window (months, not days).
• After the window, remove v1. Optionally make v2 the new "current" (sometimes drop the version prefix
entirely for default version).
Versioning strategies (beyond URL versioning)
Strategy Example
URL path /api/v2/products ← most common, easiest to debug
Custom header X-API-Version: 2
Accept header Accept: application/[Link].v2+json
Query parameter /api/products?version=2 ← rare, discouraged
EXAM Default: URL-path versioning (/v1, /v2). Easy to grep, easy to route, easy for new
developers to understand at a glance.
8. Catch-All Routes (the 404 handler)
After all your specific routes are defined, the LAST route in your router catches anything that didn’t match —
and returns a useful 404 instead of a null/empty default.
JS
Page 6 of 8
HTTP Routing · Notes
// All your real routes...
[Link]('/api/books', ...);
[Link]('/api/users/:id', ...);
[Link]('/api/auth/login', ...);
// CATCH-ALL — must come last
[Link]('*', (req, res) => {
[Link](404).json({
error: 'Not Found',
message: `Route ${[Link]} ${[Link]} does not exist`,
});
});
NOTE Why bother? Without a catch-all, hitting an unknown route may return null, a
blank 200, an HTML error page, or a stack trace — none of which help the client.
A consistent JSON 404 is much friendlier and easier to debug.
TIP Order matters! Most frameworks evaluate routes top-to-bottom. The catch-all
MUST be the last entry. Put it before specific routes and it will swallow
everything.
9. Routing Cheat-Sheet
Concept One-line takeaway
Routing Map (HTTP method + URL pattern) → handler function.
Static route Constant path string with no placeholders.
Dynamic route Path with :param slots that capture client values.
Path param Identifies WHICH resource (e.g. /users/:id).
Query param Modifies HOW the resource is returned (filter/sort/paginate).
Method dispatch Same path + different method = different handler. GET /users ≠ POST
/users.
Nested route Layer resources to express ownership: /users/:uid/posts/:pid.
Versioning Publish breaking changes under /v2, keep /v1 alive for a migration
window.
Catch-all Last route in the file. Returns a clean JSON 404 for unmatched paths.
Path-vs-query rule If it changes WHAT → path. If it changes HOW → query.
Param types Path params are strings — cast in handler if you need int/UUID/bool.
Page 7 of 8
HTTP Routing · Notes
Concept One-line takeaway
Standard query names page, limit, sort_by, order, q — stick to convention.
Mental model — anatomy of a complete API URL
URL
scheme host path query string
───── ────────────── ─────────────── ──────────────────────
https:// [Link] /api/v1/users/123/posts ?page=2&limit=20
└─ versioning ─┘ └─ nested route ─┘ └─ query params ─┘
└─ path params ─┘
End of notes — next stop: REST principles & resource design.
Page 8 of 8