🛣️ C2 · Route Definition: app.get/post, req.params/query
C2 · Route Definition: app.get/post: An Express route is like a **room number and a note left at reception**: writing `app.get('/api/v1/bugs/:id', ...)` makes `:id` a variable "r
An Express route is like a **room number and a note left at reception**: writing `app.get('/api/v1/bugs/:id', ...)` makes `:id` a variable "room number" (path parameter), while something like `?status=OPEN` is a "note" left at reception (query parameter) — one is **part of the path itself**, the other is **optional extra information**. In Spring these two are visible right in the signature via `@PathVariable` and `@RequestParam`; in Express they are read by hand in the function body with `req.params.id` and `req.query.status` — the contract lives INSIDE the function instead of the annotation. So why does some information go in the path (`/bugs/42`) and some in the query (`?status=OPEN`)? Because the path carries a resource's **identity** (this request is meaningless without bug number 42), while the query carries **optional filtering/behavior** (a list request is still valid without status). For a tester this means: `req.params` ALWAYS arrives as a string — since JavaScript has weak typing, `"1" === 1` is FALSE; this is a sneaky source of bugs in ID comparisons, and, as you will see next, a real defect.
List, Filter, and a Single Record
**🐞 Defect Birth — if the `req.params.id` type conversion is forgotten** **Code:** `bugs.find(b => b.id === req.params.id)` — `b.id` is a **number** (1, 2, ...), `req.params.id` always arrives as a **string** (`"1"`, `"2"`, ...). **What happens:** a `GET /api/v1/bugs/1` request is sent, the record EXISTS in the data, but since `1 === "1"` is `false` in JavaScript, `find` never matches — the result is always 404, even though the record exists. **Why sneaky:** reading the code, the logic looks entirely correct ("we are comparing IDs"). The failure is not a syntax or runtime exception, it is a silent logic bug — it only surfaces when a tester is confused: "this ID definitely exists, why am I getting 404?" **Where the tester catches it:** sending a GET request with a known-existing ID and getting 404 instead of 200 — a classic example of JavaScript's weak-typing trap; the fix is converting the type with `Number(req.params.id)`.
🎬 "1" ≠ 1: Why a Path Parameter Always Arrives as a String
The client sends a request to `/api/v1/bugs/1` — a URL is always made of text characters.
Express places the `:id` part into `req.params.id` as a STRING: `"1"`, not a number.
But the bug record in memory has an `id` field that is a NUMBER: `1`.
In JavaScript, `===` does NOT coerce types: `"1" === 1` is always `false`.
The lesson — `find` never matches, 404 is returned even though the record exists. The tester must verify that `Number(req.params.id)` conversion is done.
req.params vs req.query: Where Does Each Come From?
The :id in /bugs/:id arrives as req.params.id, a STRING.
Suffixes like ?status=OPEN&page=1 are placed on the req.query object, also as STRINGs.
Convert with Number(...) before numeric comparison, otherwise === always returns false.
Order the flow for fetching a single bug record by ID.