Once you can read raw HTTP, every tool, framework and error message becomes easier to understand.
HTTP is a request/response protocol: a client (browser, app, curl) sends a request; a server sends back exactly one response. Each exchange is independent: HTTP itself is stateless, and the server remembers nothing between requests unless something like a cookie or token is sent along.
In HTTP/1.1 the messages are readable text. A request is:
- a request line: method, target and version, e.g.
GET /users/42 HTTP/1.1; - header fields, one per line,
Name: value.Hostis required, because one IP address can serve many sites; - an empty line;
- an optional body, for example JSON for a POST.
A response mirrors it:
- a status line: version, status code and reason phrase,
HTTP/1.1 200 OK; - headers such as
Content-TypeandContent-Length; - an empty line, then the body: HTML, JSON, an image.
HTTP/2 and HTTP/3 encode these same parts in a binary format, but the meaning (method, path, headers, status, body) is identical, so everything you learn here carries over.
To see real traffic, use curl -v, which prints request lines prefixed with > and response lines with <, or the browser devtools Network tab, which shows each request's headers, timing and response. Reading these is the first step in debugging any web problem.
Example
$ curl -v https://example.com/ # abridged sample output
> GET / HTTP/2
> Host: example.com
> User-Agent: curl/8.11.0
> Accept: */*
>
< HTTP/2 200
< content-type: text/html
< content-length: 1256
< cache-control: max-age=3600
<
<!doctype html>
<html> ...
# The same request written as raw HTTP/1.1 text:
# GET / HTTP/1.1\r\n
# Host: example.com\r\n
# Accept: */*\r\n
# \r\nRemember
- Request = method + target + headers + optional body
- Response = status + headers + optional body
- HTTP is stateless: each request stands alone
- curl -v and the Network tab show the real messages
Watch out for
- Assuming the server remembers a previous request; state must be carried by cookies, tokens or the URL.