HTTP: Requests & Responses
A stateless text protocol — understand its shape and half of backend work stops being mysterious.
35 minDifficulty 1/5fundamentals · protocolReviewedRead and accepted by a person.
Before this
Why this exists
Almost everything you'll build sends or receives HTTP. Yet most developers learn it by osmosis — absorbing enough to make `fetch` work and never seeing the shape underneath. Spend forty minutes on the actual structure and a surprising amount of backend work stops being guesswork: CORS errors, caching bugs, auth failures and mysterious 400s all become readable.
The mental model
A letter. There's an envelope with an address and handling instructions on the outside (the request line and headers), and there's whatever you put inside (the body). The recipient replies with a letter of the same shape.
How it works
It's text, and you can read it
An HTTP request is plain text in a fixed layout: a request line, then headers one per line, then a blank line, then an optional body. That's it. Everything your framework does — routing, parsing, content negotiation — is manipulation of this structure. Once you've seen a raw request, the abstractions above it stop being magic.
It is stateless, and that is a deliberate choice
The server is not required to remember anything between two requests. Each one arrives carrying everything needed to handle it. This feels like a limitation and is actually the reason the web scales: any server can handle any request, so you can put ten machines behind a load balancer without them coordinating. Sessions, cookies and tokens all exist to *simulate* memory on top of a protocol that deliberately has none.
The response mirrors the request
A response is the same shape: a status line with a code, then headers, then a blank line, then the body. The status code is the summary — the one thing a caller can act on without parsing anything else. The headers describe the body and how to treat it: what type it is, how long to cache it, whether it's compressed.
Connections are reused, versions matter less than you'd think
Opening a TCP connection is expensive, so HTTP/1.1 keeps them alive and sends many requests over one. HTTP/2 goes further and multiplexes many requests over a single connection simultaneously, removing the head-of-line blocking that made people shard assets across domains. HTTP/3 swaps TCP for QUIC. For application code, the semantics — methods, status codes, headers — are identical across all three. The version changes performance characteristics, not what you write.
The mechanism
A raw exchange, in full: ``` GET /users/42 HTTP/1.1 Host: api.example.com Accept: application/json Authorization: Bearer eyJhbGci... ``` ``` HTTP/1.1 200 OK Content-Type: application/json Cache-Control: private, max-age=60 Content-Length: 47 {"id":42,"name":"Ada","email":"ada@example.com"} ``` The blank line is load-bearing: it's the only thing separating headers from body.
sequenceDiagram
participant B as Client
participant S as Server
B->>S: GET /users/42 HTTP/1.1
Note over B,S: Host, Accept, Authorization headers
S->>S: route, authorise, fetch
S-->>B: HTTP/1.1 200 OK
Note over B,S: Content-Type, Cache-Control, body
B->>S: GET /users/42/orders (same connection)
S-->>B: 200 OKWhat people get wrong
- HTTP and HTML are closely related.
- HTTP is a transfer protocol; it neither knows nor cares what it's carrying. HTML is one payload among many. The protocol moves bytes and describes them with Content-Type. JSON, images and video all travel identically.
- Each request opens a new connection.
- Connections are kept alive and reused by default since HTTP/1.1. TCP setup plus TLS handshake costs multiple round trips, which would dominate the cost of small requests.
- Statelessness means you can't have logged-in users.
- It means the state travels with each request, in a cookie or token, rather than living implicitly on one server. Moving the state into the request is what lets any server handle any request.
- HTTP/2 changes how I write my API.
- The semantics are unchanged. Methods, status codes and headers work exactly the same. HTTP/2 changes framing and transport efficiency, not meaning. Some old workarounds like domain sharding become counterproductive, but your handler code is untouched.
When not to use it
- You need the server to push data at any moment without the client asking.
- WebSockets or Server-Sent Events. Plain HTTP is request-response — the client must initiate.
- You need very low-latency, high-frequency messaging between your own internal services.
- gRPC or a message queue. HTTP's per-request overhead and text headers are real costs at that volume.
Terms
- Request line
- — The first line of a request: method, path, and protocol version.
- Header
- — A key-value pair carrying metadata about the message — never the content itself.
- Body
- — The actual payload. Optional; GET requests normally have none.
- Stateless
- — The server keeps no memory of previous requests. Everything needed arrives with each one.
- Keep-alive
- — Reusing one TCP connection for multiple requests instead of reconnecting each time.
- Content-Type
- — The header declaring what format the body is in, so the recipient knows how to parse it.
In an interview
What happens when you type a URL and press enter?
- DNS resolves the hostname to an IP address
- TCP connection, then a TLS handshake for HTTPS
- an HTTP request is sent: request line, headers, blank line, optional body
- the server responds with a status code, headers and body
- the browser parses and fetches subresources over the same reused connection
Why is HTTP stateless, and what does that cost you?
- any server can serve any request, so horizontal scaling needs no coordination
- the cost is that identity must travel with every request
- cookies, sessions and tokens exist to reintroduce the state that was removed
Can you recall it?
Describe the structure of an HTTP request from memory, and say why statelessness matters.
Connected ideas
- Methods & Status Codes — GET/POST/PUT/PATCH/DELETE and what your API is really telling the caller with 201 vs 204 vs 202.
- Headers, Cookies & State — How a stateless protocol fakes memory — and where every auth bug you'll ever hit lives.
- REST API Design — Resources, not verbs — designing an interface another team can use without asking you questions.