The built-in http module, why Express exists, routing, middleware pipelines, route parameters, query strings, and sending JSON responses.
Module F-6 — Building HTTP Servers and REST APIs with Express
What this module covers: Express is the most widely used Node.js web framework — and for good reason. It takes the built-in
httpmodule and adds routing, middleware, and a clean request/response API without imposing a rigid structure. This module covers everything you need to build a real REST API: routing, route parameters, query strings, request bodies, middleware pipelines, and error responses. By the end you will have a working multi-route API with proper HTTP semantics.
From Raw http to Express
You saw the built-in http module in F-1:
This works, but it has no routing. Every request — regardless of URL or method — hits the same handler. To build a real API you need to route GET /users to one handler, POST /users to another, DELETE /users/:id to a third. You also need to parse JSON bodies, read headers, set response codes properly, and handle errors consistently.
You could implement all of that yourself on top of http. Express already did it — and did it well.
Your First Express Server
The Express API:
express()creates an application instanceapp.use(...)adds middleware (runs on every request)app.get(path, handler)registers a GET routereq— the incoming request objectres— the response objectres.json(data)— sends JSON withContent-Type: application/jsonand status 200
HTTP Methods and REST Conventions
REST APIs use HTTP methods to express intent:
| Method | Meaning | Example |
|---|---|---|
GET | Read a resource | GET /users — list all users |
POST | Create a resource | POST /users — create a user |
PUT | Replace a resource entirely | PUT /users/42 — replace user 42 |
PATCH | Update part of a resource | PATCH /users/42 — update user 42's email |
DELETE | Remove a resource | DELETE /users/42 — delete user 42 |
Express has a method for each:
Route Parameters
Route parameters are named placeholders in the URL path, prefixed with :. Express captures them and puts them in req.params.
Important: route parameters are always strings, even if the URL contains a number. Convert them explicitly:
Query Strings
Query strings are the ?key=value part of a URL. Express parses them automatically into req.query.
Query string values are always strings — convert them as needed.
Request Bodies
For POST, PUT, and PATCH requests, data comes in the request body. With express.json() middleware registered, Express automatically parses JSON bodies into req.body.
For URL-encoded forms (HTML form submissions):
HTTP Status Codes
Always respond with the appropriate status code. Clients use these to understand what happened.
Middleware
Middleware is the backbone of Express. A middleware function receives (req, res, next) and either:
- Responds to the request (ends the chain), or
- Calls
next()to pass control to the next middleware or route handler
Writing a custom middleware
Middleware that adds data to the request
Middleware that can stop the chain
Express Router
As your API grows, keeping every route in index.js becomes unmanageable. Use express.Router() to split routes into separate files:
Error Handling
Express has a special error-handling middleware signature: four arguments (err, req, res, next). Register it after all routes.
We cover a much cleaner error handling pattern — with custom error classes and an async wrapper — in P-4. For now this structure works.
Reading Headers and Setting Response Headers
A Complete Working Example
Here is a minimal in-memory users API that uses everything from this module:
Test it with curl:
Summary
- Express wraps Node's
httpmodule with routing, middleware, and a clean API. Install withnpm install express. - Routes are registered with
app.get,app.post,app.put,app.patch,app.delete. The path and handler are separate concerns. - Route parameters (
/users/:id) are inreq.params. Always strings — convert them. - Query strings (
?page=1&limit=20) are inreq.query. Also always strings. - Request body (POST/PUT/PATCH) is in
req.bodyafter registeringapp.use(express.json()). - Status codes are set with
res.status(code). Use them correctly — 201 for creation, 204 for deletion, 404 for not found, 400 for bad input. - Middleware runs in registration order. Call
next()to continue, or respond to end the chain. - Routers split routes into files. Mount them with
app.use('/prefix', router). - Error handler has four arguments
(err, req, res, next)and must be registered last.
Next: connecting to a real database from Node.js — PostgreSQL with node-postgres, parameterized queries, and a first look at Prisma.
When accessing a route parameter in Express (e.g., /users/:id), what data type is the parameter req.params.id?
In an Express middleware function, what happens if you neither send a response (e.g., res.json()) nor call next()?
What is the correct function signature for a global error-handling middleware in Express?
Test your knowledge with more question sets
Sign in to access a wider variety of questions and get notified when new practice sets are added to this module.
Sign in & RegisterDiscussion
0Join the discussion