Node.js HTTP Module

Build a web server from scratch using Node's built-in http module — no framework required.

The Built-in http Module

Node.js ships with an http module that lets you create a fully functional web server without installing anything. It's the foundation every Node.js framework (Express, Koa, Fastify) is ultimately built on top of.

Creating a Server

http.createServer() takes a callback that runs once for every incoming request. The callback receives a request object (req) describing what the client asked for, and a response object (res) you use to send data back. Calling .listen() starts the server on a given port.

server.js

// server.js
const http = require("http");

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain");
  res.end("Hello from Node.js!\n");
});

server.listen(3000, () => {
  console.log("Server running at http://localhost:3000/");
});

// Run with: node server.js, then visit http://localhost:3000/
Note: The server keeps the Node.js process alive on its own — you don't need a loop or a sleep call. As long as server.listen() is active, Node's event loop stays open waiting for connections.

Reading the Request: Method and URL

router.js

// router.js
const http = require("http");

const server = http.createServer((req, res) => {
  res.setHeader("Content-Type", "application/json");

  if (req.method === "GET" && req.url === "/") {
    res.statusCode = 200;
    res.end(JSON.stringify({ message: "Welcome home" }));
  } else if (req.method === "GET" && req.url === "/about") {
    res.statusCode = 200;
    res.end(JSON.stringify({ message: "About this API" }));
  } else {
    res.statusCode = 404;
    res.end(JSON.stringify({ error: "Not found" }));
  }
});

server.listen(3000, () => console.log("Listening on port 3000"));
  • req.method — the HTTP verb: GET, POST, PUT, DELETE, etc.
  • req.url — the requested path and query string, e.g. /about?ref=home.
  • req.headers — an object containing the incoming request headers.
  • res.statusCode / res.setHeader() / res.end() — control the outgoing response.
MethodStatus CodeTypical Body
GET (found)200 OKThe requested data
POST (created)201 CreatedThe newly created resource
Unmatched route404 Not FoundAn error message

echo-server.js

// echo-server.js
const http = require("http");

const server = http.createServer((req, res) => {
  if (req.method === "POST") {
    let body = "";
    req.on("data", (chunk) => (body += chunk));
    req.on("end", () => {
      res.statusCode = 200;
      res.setHeader("Content-Type", "application/json");
      res.end(JSON.stringify({ received: body }));
    });
  } else {
    res.statusCode = 405;
    res.end("Method Not Allowed");
  }
});

server.listen(3000, () => console.log("Echo server on port 3000"));
Note: Never leave a route unhandled without sending a response — if res.end() is never called, the client's connection hangs until it times out. Always make sure every code path terminates the response, including error cases.

Exercise: Node.js HTTP Module

Which built-in Node.js module is used to create a basic web server?