Dynamic Content & Forms
Website Rebuild with Express
Chapter 8 · Dynamic Content & Forms
Astro's own request.json() needed zero setup — it's a standard Web API method on any Request object. Express needs one more step before req.body is even populated at all.
Without express.json(): req.body Is Undefined
request.json() works immediately, on any request, with nothing to configure — it's inherent to the standard Request object itself. Express requires an explicit middleware, express.json(), registered before any route can see a parsed body at all. Without it, req.body isn't an empty object — it's genuinely undefined, and code that assumes otherwise crashes.
Registering It, and Validating with Zod
Zod — the same choice Astro made — closes the same real gap: nothing in Express validates types, lengths, or required fields on its own.
The Deliberate No-Auth-Check-Yet Gap
Matching every sibling course's own Chapter 8, no authentication check exists yet, to be closed in Chapter 9. Like Astro's own version, there's no conventional place for one to go yet — Express provides nothing resembling before_action or authorize() to even have a placeholder in.
No CSRF Protection — Repeated Honestly a Final Time
protect_from_forgery, Laravel's VerifyCsrfToken, or Django's own CSRF middleware. A cross-origin request could hit this endpoint with no built-in defense at all, the identical gap Astro's own Chapter 8 named and left honestly unsolved.
Request Body Parsing, Compared
| Astro | Express | |
|---|---|---|
| Setup required? | None — request.json() is a standard Web API method | Explicit — app.use(express.json()) required |
| Behavior with no setup | Works by default | req.body is genuinely undefined |
Hands-On Exercises
Without registering express.json(), send a real JSON POST request and confirm req.body is undefined, causing naive destructuring code to throw.
📄 View solutionAdd express.json() and the Zod validation, then send a malformed request (e.g. a numeric title) and confirm it's now rejected with a 400 response.
📄 View solutionConfirm no CSRF protection exists by successfully calling this endpoint from a genuinely different origin, with no same-origin check blocking it.
📄 View solutionChapter 8 Quick Reference
app.use(express.json())— required just to getreq.bodypopulated at all- More minimal than Astro — Astro's
request.json()needs zero setup; Express'sreq.bodyisundefinedwithout one - Zod's
safeParse— the same deliberate choice Astro made, closing the same real validation gap - No CSRF protection — the identical unaddressed gap named in Astro's own Chapter 8
- Next chapter: Admin Authentication