⛓️ C3 · Middleware Chain: express.json(), order
C3 · Middleware Chain: express.json(): A middleware chain is like an **airport security corridor**: a passenger (request) passes through check-in, baggage scan, and passport cont
A middleware chain is like an **airport security corridor**: a passenger (request) passes through check-in, baggage scan, and passport control in order; each checkpoint (`function(req, res, next)`) can inspect the passenger, attach something (a baggage tag), or stop them — and moving to the next checkpoint happens ONLY if `next()` is called. `express.json()` is exactly such a checkpoint: it reads the incoming JSON body and "tags" it onto `req.body` before handing off to the route handler. So why does Spring do this automatically with a single `@RequestBody` annotation while Express needs a separate step? Because behind Spring MVC there is a ready-made request-processing pipeline (the dispatcher servlet) and body parsing is a standard part of that pipeline; Express has NO such pipeline — you build the chain by hand, in order; the closest Java equivalent is the Servlet **Filter** chain (each filter blocks the next until `chain.doFilter()` is called). The critical point for a tester: the ORDER of middleware determines behavior — if `express.json()` is defined after the routes, the routes never see a parsed body; this is the sneakiest kind of bug, the "code is correct but the order is wrong" category.
Building the Chain: Why Order Is Critical
**🐞 Defect Birth — if `express.json()` is defined AFTER the routes** **Code:** `app.post('/api/v1/bugs', ...)` comes first, `app.use(express.json())` sits at the bottom. **What happens:** a `POST /api/v1/bugs { "title": "...", "severity": "HIGH" }` request is sent; when the handler runs, `req.body` is STILL `undefined` because the parser middleware sits LATER in the chain. `const { title, severity } = req.body` does not crash (destructuring `undefined` yields `undefined`), the server returns `201 Created` but creates a record with `title: undefined, severity: undefined`. **Why sneaky:** the request looks "successful" with 201, the server does not crash, there is no error log — yet an entirely empty bug record is created in the data store. The code ITSELF (the `express.json()` call) is correct, the only problem is its ORDER. **Where the tester catches it:** reading the record back with a GET after the POST and seeing `title` come back as `null`/`undefined` — this is the classic "got 201 but the content is empty" middleware-ordering bug.
🎬 The Middleware Chain: What Happens When the Order Breaks?
Order broken: req.body = undefined
GET evidence: title arrived empty
The client sends a `POST /api/v1/bugs` request with the body `{ "title": "Login freezes", "severity": "HIGH" }`.
IN THE CORRECT ORDER: the request first hits `express.json()` — the raw JSON text is parsed into the `req.body` object.
Then the logger middleware logs the request and hands off with `next()` to the next link — the chain continues unbroken.
The route handler runs — `req.body.title` is filled, the record is created correctly, 201 with real data is returned.
IN THE WRONG ORDER: if `express.json()` is defined AFTER the routes, `req.body` is STILL `undefined` when the handler runs.
The server still returns `201 Created` — the code does not crash, but an empty record is created with `title: undefined`.
The lesson — ORDER in a middleware chain determines behavior independently of the code itself. A tester does not settle for "I got 201"; they also verify the returned/stored data.
A POST Request's Journey Through the Chain