Chapter 1. What the Web Is

Vague but exciting…

— Mike Sendall, on Tim Berners-Lee’s 1989 proposal

Nothing in this chapter is mine. That is the point of it.

The web ships with its own definitions, and they are shorter than you probably expect. There are identifiers:

I     the set of URIs                                    (RFC 3986)

There are requests, which HTTP (RFC 9110) builds from identifiers:

Req = I × Method × Headers × Body                        (RFC 9110)

The body may be empty; the empty body is a body, the way an empty set is a set. Requests with a safe method (RFC 9110’s word for the methods that only ask, never change) almost always leave it empty. Definition 1.1 shows what the unsafe methods use the body for. (RFC 9110’s own name for it is content, a word this book will need for something else, so the older wire name stays.)

Responses come back the same shape, because RFC 9110 defines one message form for both directions. Where the request had a method and an identifier, the response has a status code:

Resp = Status × Headers × Body                           (RFC 9110)

For the model below, only the response body matters. The body itself is octets. A header names their format (Content-Type). How the octets parse is defined by the format’s own specification, so the book does not have to define it. On the parsed side of that line lives the document, the thing a user agent displays. Call that domain Doc, and leave its internals alone for now. The envelope around it (the status code, the response headers) is how a document travels, ages, and caches. That is transfer machinery, and Definition 1.1 will not mention it.

Definition 1.1. A web application is a pair of functions, read and write:

read  : Req × State → Doc
write : Req × State → State

In this model, read corresponds to HTTP’s safe methods: GET takes a request and the current state of the world and produces a document. write is what the unsafe methods do: POST, PUT, PATCH, DELETE take a request and a state and produce a new state. The request’s body carries what the change should be. The body belongs to the write side: on a safe request it has no defined meaning (RFC 9110 §9.3.1), and read ignores it. read’s output travels in the response’s body instead. Like Doc, Body stays opaque for now; Chapter 7 defines its contents.

Every web application you have ever used implements these two functions — from a static homepage to the heaviest single-page application — because HTTP gives it no other way to be an application on the web. The framework it was built in is an implementation detail of Definition 1.1.

Definition 1.1 deliberately leaves State unspecified. The central question of the book is therefore: what properties must State have? Part II derives those properties from constraints of the web, and Part III shows how they correspond to existing standards.

Prop. 1.2. Every deployed web application implements Definition 1.1. (Verification: RFC 9110 §9; there is no third kind of method.)

Prop. 1.3. Definition 1.1 places no constraint on architecture. Both a 1993 CGI script and a 2026 React application satisfy it. (This is why the definition is safe as an axiom; no one on any side of any framework war can reject it.)

Persistent connections — why WebSockets and server push are not a counterexample.

WebSockets (an open two-way message channel between browser and server) and server push may look like a counterexample because messages on an established connection are not themselves HTTP requests with safe or unsafe methods. At the application level, however, they still carry either data from the server to the client or changes from the client to the server. The first corresponds to read output delivered when state changes; the second corresponds to input to write delivered over an existing channel. Definition 1.1 therefore still describes the application behavior. What changes is the surrounding HTTP machinery: individual messages no longer necessarily have their own method, cache semantics, or URI. Each dropped piece has a cost; Part IV computes those costs one by one.

The web succeeded against contemporaries such as Gopher, BBSs, desktop applications, and Java applets; Chapter 12 revisits that comparison. It succeeded because its read was transparent: documents were declarative, addressable, linkable, indexable, and legible to machines that did not produce them. Part IV evaluates later technologies on one variable: how much of that transparency they preserve. Chapter 21 makes the term exact. Before doing that, the undefined State in Definition 1.1 needs a model. Chapter 2 explains the method used to derive one rather than selecting it from current practice or personal preference.