Built-in Middleware
Objectives
By the end of this lesson, you should be able to:
- Use
express.json()to parse JSON request bodies - Use
express.urlencoded()to parse HTML form submissions - Recognize
express.static()(Module 5) as another built-in middleware
💡 Why this matters:
express.json()has already been used since Module 5 without being named as what it actually is, middleware. This lesson makes that explicit, and addsexpress.urlencoded()for the other common request body format, traditional HTML form submissions.
⚠️ A note on verification: every snippet and every response shown below was actually run and tested with real HTTP requests.
express.json() Is Middleware
app.use(express.json());
This exact line has appeared since Module 5, express.json() returns a middleware function, and app.use() registers it, exactly like the custom logger middleware from Lesson 1. It inspects the request’s Content-Type header, and if it’s application/json, parses the body and attaches the result to req.body, this is precisely how req.body becomes available in a route handler.
express.urlencoded() for Form Submissions
const express = require('express');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.post('/json-body', (req, res) => {
res.json({ received: req.body });
});
app.post('/form-body', (req, res) => {
res.json({ received: req.body });
});
app.listen(4203);
curl -X POST http://localhost:4203/json-body \
-H "Content-Type: application/json" -d '{"name":"Sam"}'
{"received":{"name":"Sam"}}
curl -X POST http://localhost:4203/form-body \
-H "Content-Type: application/x-www-form-urlencoded" -d 'name=Sam&role=admin'
{"received":{"name":"Sam","role":"admin"}}
A traditional HTML <form> submission sends its data as Content-Type: application/x-www-form-urlencoded, not JSON, name=Sam&role=admin rather than {"name":"Sam"}. express.urlencoded({ extended: true }) parses this format into req.body, exactly the same shape as express.json() produces for JSON, { extended: true } allows nested objects and arrays in the parsed result, the standard setting for this option.
Multiple Body Parsers Can Coexist
Both express.json() and express.urlencoded() are commonly registered together, each only activates for requests with the matching Content-Type, a JSON request is unaffected by express.urlencoded() being registered, and vice versa, this is why server3.js above handles both /json-body and /form-body correctly from the same app.
express.static() Revisited
Module 5’s express.static(folderPath) is this exact same pattern, a built-in function that returns middleware, registered with app.use(). Recognizing express.json(), express.urlencoded(), and express.static() as three instances of the same underlying mechanism, rather than three unrelated features, is the real point of this lesson.
Try It
- Build a form (or simulate one with
curl -d 'field=value'and the correctContent-Typeheader) and confirmexpress.urlencoded()parses it intoreq.bodycorrectly. - Register both
express.json()andexpress.urlencoded()on the same app, and send one request of each type, confirming both are parsed correctly without interfering with each other. - Remove
express.urlencoded()temporarily, send a form-encoded request, and confirmreq.bodyis nowundefinedor empty. - Explain, in your own words, why
express.static(),express.json(), andexpress.urlencoded()are all considered the same kind of thing, middleware, even though they do very different jobs.
Recap
express.json()parses a JSON request body intoreq.body, activating only forContent-Type: application/jsonrequests.express.urlencoded({ extended: true })parses traditional HTML form submissions intoreq.body, in the same shape.express.static(),express.json(), andexpress.urlencoded()are all built-in functions that return middleware, registered withapp.use().
Next lesson: writing your own custom middleware.