`req`, `res`, and What's On Them
Building a Server
Inspect the request — method, URL, headers, body. Build the response — status, headers, body.
What you'll learn
- Read req method, URL, headers
- Set status, headers, body on res
- Send JSON responses
Every request triggers your handler with two objects: req
(IncomingMessage) and res (ServerResponse). Both are streams.
Reading the Request
import { createServer } from "node:http";
createServer((req, res) => {
console.log(req.method); // 'GET', 'POST', ...
console.log(req.url); // '/users/42?expand=true'
console.log(req.headers); // { host: ..., 'user-agent': ... }
res.end("ok");
}).listen(3000); req.url is the raw URL string. To split path/query:
const url = new URL(req.url, `http://${req.headers.host}`);
console.log(url.pathname); // '/users/42'
console.log(url.searchParams.get("expand")); // 'true' Writing the Response
res.statusCode = 200;
res.setHeader("Content-Type", "text/plain");
res.end("Hello!"); Or all-in-one with writeHead:
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello!"); res.end() finishes the response. Forget to call it and the
request hangs.
Sending JSON
No built-in helper — do it explicitly:
function json(res, status, data) {
res.writeHead(status, { "Content-Type": "application/json" });
res.end(JSON.stringify(data));
}
createServer((req, res) => {
if (req.url === "/api/user") {
return json(res, 200, { id: 1, name: "Ada" });
}
json(res, 404, { error: "not found" });
}).listen(3000); This is the kind of helper Express bakes in (res.json(obj)).
Reading the Request Body
POST/PUT bodies arrive as a stream:
async function readBody(req) {
const chunks = [];
for await (const chunk of req) chunks.push(chunk);
return Buffer.concat(chunks).toString("utf8");
}
createServer(async (req, res) => {
if (req.method === "POST") {
const text = await readBody(req);
const data = JSON.parse(text);
// ...
res.end("ok");
} else {
res.end("only POST");
}
}).listen(3000); Again — Express/Fastify do this for you.
Routing →