Every route handler in Express receives a request object and a response object. This lesson covers the properties and methods on req and res you will use in almost every handler you write.
What Are req and res?
req represents the incoming HTTP request, it holds the URL, headers, method, route parameters, query string, and (once parsed by middleware) the body. res represents the outgoing HTTP response, offering methods to set status codes, headers, and the response body.
Both objects are Express-enhanced versions of Node's raw http.IncomingMessage and http.ServerResponse, meaning all the low-level Node properties still exist, plus the extra convenience methods Express adds.
req.params only exists for named route segments like :id.
req.body is undefined unless a body-parsing middleware (like express.json()) ran first.
res methods are chainable, e.g. res.status(201).json(user).
Only one final response method (send, json, redirect, end, ...) should run per request.
req / res Cheatsheet
The properties and methods you will reach for constantly while writing Express handlers.
Member
Example
Description
req.params
req.params.id
Named route segment values
req.query
req.query.page
Query string values
req.body
req.body.email
Parsed request body
req.headers
req.headers['authorization']
Request headers (lowercased)
req.get()
req.get('Content-Type')
Reads a single header
res.status()
res.status(404)
Sets the HTTP status code
res.json()
res.json({ ok: true })
Sends JSON with correct headers
res.redirect()
res.redirect('/login')
Sends a 302 redirect
Reading Data From the Request
A single route often needs to combine several sources of input: route parameters for identifying a resource, query parameters for filtering or pagination, and the body for data being created or updated.
You must send exactly one response per request. Express does not automatically end the response, if a handler never calls a terminating method like res.send(), res.json(), or res.end(), the client's connection hangs until it times out.
Method
When to Use
res.send(str)
Plain text or HTML
res.json(obj)
Structured JSON data
res.status(code).json(obj)
JSON with a specific status code
res.sendStatus(code)
Status-only response, e.g. 204
res.redirect(url)
Redirect the client to another URL
Common Mistakes
Calling two terminating response methods in the same handler (e.g. res.send() then later res.json()), causing a "headers already sent" error.
Reading req.body without first registering express.json() or express.urlencoded().
Confusing req.params (route segments) with req.query (the query string).
Forgetting return after sending an early response inside a conditional, letting code fall through and try to respond twice.
Key Takeaways
req describes the incoming request; res builds the outgoing response.
req.params, req.query, and req.body are the three main sources of client input.
Exactly one terminating response method should run per request.
Chain res.status() before res.json()/res.send() to set a non-default status code.
Pro Tip
Add return before every response call inside conditional branches (return res.status(400).json(...)), it is a small habit that prevents an entire class of double-response bugs.
You now understand how to read requests and shape responses. Next, learn how Express matches incoming requests to handlers in the Express Routing lesson.