Konrad Kowalski (rootsher)Principal Platform & Reliability Architect110110101010011110100110000011110100001111000011

The Layers of HTTP in the Browser: From fetch() to QUIC

date
category
Frontend
also in
Backend · Networking
reading
1 min / 243 words

In frontend code HTTP often looks like this:

js
const response = await fetch("/api/users/42");
const user = await response.json();

Two lines hide several different layers:

text
Fetch API
   |
   v
browser security / cache / cookies
   |
   v
HTTP semantics
   |
   v
HTTP/1.1, HTTP/2 or HTTP/3
   |
   v
TCP or QUIC
   |
   v
TLS

This series goes below fetch(), but it stays a series for the frontend.

We will not implement an HTTP parser or tune a server kernel. What matters here is what directly affects an application in the browser:

  • why a 404 does not reject the promise from fetch(),
  • what makes GET different from POST beyond the name,
  • why retrying a POST can be dangerous,
  • where the request headers we never set come from,
  • why JavaScript cannot control some headers,
  • when the browser sends a body, cookies and credentials,
  • why HTTP/1.1 produced a different waterfall than HTTP/2,
  • what multiplexing really gives you,
  • why HTTP/3 changed the transport but not the semantics of GET /api/users,
  • what happens between fetch() and the first byte of the response.

One distinction runs through the whole series:

text
browser API
!=
HTTP semantics
!=
HTTP wire protocol
!=
transport

fetch() is a browser API.

GET, POST, status codes and headers belong to HTTP semantics.

HTTP/1.1, HTTP/2 and HTTP/3 encode and carry those semantics in different ways.

TCP and QUIC sit lower still.

That is why the same code:

js
fetch("/api/users")

can be carried by HTTP/1.1, HTTP/2 or HTTP/3 without changing the application.

We will go through:

text
request / response
      |
      v
methods + status codes
      |
      v
headers + body
      |
      v
browser-controlled HTTP
      |
      v
connections
      |
      v
HTTP/1.1
      |
      v
HTTP/2
      |
      v
HTTP/3 + QUIC
      |
      v
full fetch lifecycle

By the end the Network panel in DevTools should stop looking like a list of requests.

It should look like a record of the decisions made by the browser, the protocol and the network.