node:http — A Minimal HTTP Server

Node's built-in HTTP server module — request/response handling with no framework, and why every input from it is untrusted.

                createServer((req, res) => {}).listen(port)
              

Purpose

node:http provides a low-level HTTP server with no framework layered on top — request routing, body parsing, and similar are left to application code or a framework (Express and others) built on this same module.

Syntax

import { createServer } from 'node:http';

const server = createServer((req, res) => {
  if (req.url === '/health') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('OK');
    return;
  }
  res.writeHead(404);
  res.end('Not found');
});

server.listen(3000);

Behavior notes

  • The request body isn’t parsed automatically — it arrives as a readable stream (req.on('data', …) / req.on('end', …), or for await (const chunk of req)), and must be collected and parsed manually (or via a framework/middleware) for JSON or form data.
  • req.url, headers, and the body are all client-supplied and must be treated as untrusted input — validated the same way any external input is, before being used to build a file path, database query, or any other sensitive operation.
  • res.writeHead(status, headers) must be called before res.write()/res.end() — headers can’t be sent after the body has started.

Common mistakes

  • Trusting req.url or header values without validation, opening the door to path traversal or injection if that data flows into a file path, command, or query unmodified.
  • Forgetting to call res.end(), leaving a request hanging indefinitely with no response sent.

Runtime notes

Node-specific — a browser has no equivalent, since a browser is an HTTP client, not typically a server.

Taught in these lessons