Chapter 10 of 18 · Node.js for Beginners — Complete Free Tutorial

How HTTP Works

The Node.js for Beginners series now turns from running scripts to serving the world: HTTP. Every API you have ever consumed speaks it, and every server you will build from here on implements it. This chapter explains the conversation itself — what a request contains, what a response contains, which verbs and status codes exist, and why the exchange is deliberately stateless.

The request-response cycle

HTTP (HyperText Transfer Protocol) is a text-based, request-response protocol. The shape of every interaction never changes:

  1. A client — browser, curl, mobile app — opens a connection to a host and port (80 for HTTP, 443 for HTTPS).
  2. The client sends a request: a start line, headers, an optional body separated by a blank line.
  3. The server replies with a response in the same shape: a status line, headers, an optional body.
  4. The connection closes, or — in modern HTTP — stays open and is reused for the next exchange.

Two consequences define everything that follows: the client always speaks first (servers never dial the browser), and each request stands alone — the server has no memory of you unless you bring proof (chapter 17).

Anatomy of a request

GET /api/todos?done=false HTTP/1.1
Host: localhost:3000
User-Agent: curl/8.7.1
Accept: application/json

  • Start line — method, request target, protocol version: GET, path plus query string, HTTP/1.1.
  • Headers — metadata written as Name: value, one per line. Host is required; HTTP/1.1 clients always send it.
  • Blank line — the mandatory separator between headers and body. Remove it and the message is garbage.
  • Body — optional. GETs rarely carry one; POST and PATCH usually do, with a Content-Type header describing its format.

Anatomy of a response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 58
Date: Sat, 03 Oct 2026 09:14:02 GMT

{"id":1,"title":"Learn HTTP","done":false}

The first line is now a status line: protocol version, three-digit status code and a reason phrase. After the blank line comes the body — here, a JSON document. You can watch a real exchange with curl, which prints the response headers alongside the body:

curl -i -s https://example.com | head -n 6

Expected output:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Accept-Ranges: bytes
Age: 589243
Date: Sat, 03 Oct 2026 09:14:02 GMT

<!doctype html>

The -i flag is the interesting one — without it curl hides the status line and headers, which are usually where the answers are.

Methods: the verbs of the API

MethodMeaningBody?Idempotent?
GETRead a resourceUnusualYes — asking twice changes nothing
POSTCreate (or submit)YesNo — each call creates another
PUTReplace a resource entirelyYesYes — same payload, same end state
PATCHUpdate part of a resourceYesNot necessarily
DELETERemove a resourceRarelyYes — deleting twice is still deleted

Idempotent is the word to remember: a network timeout may force a client to retry, and retries must not duplicate work. That property is why GET, PUT and DELETE may be repeated safely while POST cannot — and why safe designs make POSTs detectable with client-generated ids.

Status codes: how it went

ClassMeaningCommon codes
2xx SuccessEverything worked200 OK, 201 Created, 204 No Content
3xx RedirectionLook somewhere else301 Moved Permanently, 304 Not Modified
4xx Client errorFix your request400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 422 Unprocessable, 429 Too Many Requests
5xx Server errorFix my server500 Internal Server Error, 502 Bad Gateway, 503 Unavailable

The split is a contract: 4xx means the caller is wrong, 5xx means you are wrong. Returning 200 with an error in the body breaks caches, monitoring and every client library that checks the status first — chapter 15 uses this table verbatim.

Headers, statelessness and HTTPS

  • Content-Type — what the body is (application/json, text/html); servers use it to decide how to parse.
  • Content-Length — body size in bytes, so the reader knows when the message ends.
  • Authorization — credentials carried per request, the backbone of stateless APIs.
  • CORS headers — browser-only permission slips for cross-origin calls; chapter 17 owns this topic.

Statelessness means each request must carry everything needed to understand it — no server-side session assumed. It is what lets you add a second server tomorrow without shared memory. Cookies and tokens layer identity back on top without breaking the model. HTTPS is HTTP encrypted with TLS: identical status codes and headers, but unreadable on the wire — mandatory in production, and terminated either by your Node process or, more commonly, by the platform in front of it (chapter 18).

Common mistakes

  • 200 for failures — an error body with a success status defeats every client's error handling.
  • POST for reads — GETs are cacheable, retryable and loggable; POSTs are none of those.
  • Forgetting the blank line — hand-rolled HTTP without the header/body separator never parses.
  • Confusing 401 with 403 — 401 says "who are you?" (authenticate), 403 says "not for you" (authorise).
  • Assuming state lives on the server — every request arrives amnesiac; send the token, filter the query.

Practice checklist

  1. Run curl -i -s https://example.com and identify the status line, headers and body in the output.
  2. Write out by hand the full request for fetching /api/todos/3 with Accept: application/json.
  3. Match five real-world situations to status codes: missing file, bad JSON, rate limit hit, deleted item, crashed handler.
  4. Explain to a friend why retrying a GET is safe but retrying a POST can duplicate an order.
  5. Compare curl -s and curl -i -s on the same URL and note what -i adds.

You can now read the protocol — time to answer it yourself, by hand, with nothing but Node. Next: Building a Server with the http Module.

Quiz: How HTTP Works

5 questions · 70% to pass

Frequently Asked Questions

Node.js is a runtime that executes JavaScript outside the browser. It combines Google's V8 engine with APIs for files, networks, processes and streams, plus a package ecosystem (npm). You use it to build servers, command-line tools, APIs and anything that needs JavaScript running on a machine rather than in a page.

JavaScript is the language; Node.js is one environment that runs it. In the browser the language comes with a DOM, events and window APIs — in Node those are replaced by the file system, network and process modules. Syntax, functions, arrays, promises and async/await are identical, so your JavaScript knowledge transfers directly.

Browser code is sandboxed: it cannot read your files or open arbitrary ports. Node code has full machine access, which is why it is used for servers and tools but also why you never run untrusted code in it. There is no document or window in Node — the equivalents are global, process and modules.

npm is JavaScript's package manager and public registry. package.json describes your project: name, entry point, dependencies with version ranges, and scripts such as npm run dev. Installing a package copies it into node_modules and records the exact intent in package-lock.json so every machine installs identical versions.

Express is a minimal web framework for Node: a few thousand lines that give you routing, middleware, request parsing and static files on top of the raw HTTP server. It is the most common starting point for REST APIs and the backbone of this tutorial's project chapters.

Both work. CommonJS (require/module.exports) is the classic Node format; ES modules (import/export) are the standard and activated in a package.json with "type": "module". Modern projects favour ESM for browser compatibility, but you will read both in existing code, so this course teaches each.

Middleware are functions that run between the incoming request and the final response, in order: body parsing, logging, authentication, rate limits, error handling. Each receives the request, response and next function and can respond itself or pass control along — Express's pipeline model in one sentence.

A JSON file is perfect for learning CRUD: no setup, readable data, easy to reset. The moment you need concurrent writes, querying or multiple users, move to a real database — MySQL/PostgreSQL for relational data or MongoDB for documents. The storage chapter isolates persistence behind one module so swapping it later is straightforward.

A REST API exposes resources over HTTP using verbs on URLs: GET /api/todos lists, POST creates, PUT or PATCH updates, DELETE removes, and everything answers with JSON plus correct status codes (200, 201, 400, 404, 500). It is stateless — each request carries its own authentication — which makes it easy to cache, scale and consume from any frontend.

Node apps are long-running processes, not static files: deploy them to a Node-friendly host (a VPS, Render, Railway or Fly.io), keep secrets in environment variables, terminate HTTPS at a reverse proxy or platform edge, and send logs somewhere durable. The final chapter covers the full checklist including health checks and graceful shutdown.