The HTTP-foundations notes each take one contract and show single pieces of evidence. This tutorial walks the whole path a single client request touches, in order, using only read-only commands. By the end you will have reproduced, on any live static edge, the checks those notes describe — without changing its state.

We use www.xbcatm.com throughout. Replace it with the host you are inspecting. Every command below is read-only: it reads headers, requests metadata, or asks for a specific range; none of them writes to the origin.

1. Start with what a method may ask

Before you read a response body, pin down what the server will allow you to ask. A static origin has no transactions, so most mutating methods are rejected explicitly. Ask the edge what it allows:

$ curl -s -o /dev/null -w 'OPTIONS -> HTTP %{http_code}\n' -X OPTIONS https://www.xbcatm.com/
OPTIONS -> HTTP 405

405 Method Not Allowed is the honest answer. The http-method-semantics note explains why this is the contract a static origin should keep: every method is either supported with documented semantics or rejected with a status that says so. The dangerous failure mode is a proxy or imported handler that converts a rejected method into a silent 200. If your edge ever answers 200 to POST, the promise is no longer visible.

2. Read the representation line

The first line tells you the negotiated exchange; the headers then tell you what kind of bytes are coming. Capture them exactly as a client sees them, discarding the body:

$ curl -s -D - -o /dev/null https://www.xbcatm.com/
HTTP/2 200
accept-ranges: bytes
content-length: 15890
content-security-policy: default-src 'self'; base-uri 'self'; form-action 'none'; frame-ancestors 'none'; object-src 'none'; script-src 'none'; style-src 'self'; img-src 'self' data:
content-type: text/html; charset=utf-8
etag: "dkx84jwth7nkc9e"
last-modified: Mon, 24 Aug 2026 13:55:23 GMT
strict-transport-security: max-age=31536000; includeSubDomains
x-content-type-options: nosniff

Three headers deserve a pause. content-type: text/html; charset=utf-8 names the media type, and content-type-and-nosniff shows why it must describe the actual bytes you send. etag: "dkx84jwth7nkc9e" hands you a strong validator. x-content-type-options: nosniff bids a browser not to guess the type. Each is evidence, not decoration, and together they say: this edge tells you exactly its policy before you trust the body.

3. Confirm HEAD equals GET but carries no body

HEAD must be safe and return the same metadata as GET, without a body. Compare the HEAD Content-Length (the bytes GET would return) with what you actually READ:

$ curl -sI https://www.xbcatm.com/ | grep -i content-length
content-length: 15890
$ curl -s https://www.xbcatm.com/ | wc -c
15890

They match: 15890 on both. That is the head-request-parity contract. If a proxy strips or rewrites the HEAD Content-Length, a pair of checks like this catches it. This is exactly why check-http-headers.sh reads status and headers together with curl and why the release smoke tests compare HEAD before and after a swap.

4. Ask for precise bytes with a range

Because the origin knows its representation, it can serve part of it. A range request asks for a byte span and gets only that span:

$ curl -s -o /dev/null -H 'Range: bytes=0-99' -w 'HTTP %{http_code} bytes=%{size_download}\n' https://www.xbcatm.com/
HTTP 206 bytes=100

206 with 100 bytes for a 100-byte range is the honest result. The http-range-requests note explains how the server selects which bytes and why a strong validator is required. If a server answers 200 with the full body to any range instead, that is a different, more expensive contract — and it tells you the origin does not track the byte identity you asked for.

5. Let the cache revalidate with a validator

Now combine method, representation, and byte selection through caching. A stored copy is current only if the validator still matches. Replay your ETag conditionally:

$ curl -s -o /dev/null -w 'HTTP %{http_code}\n' -H 'If-None-Match: "dkx84jwth7nkc9e"' https://www.xbcatm.com/
HTTP 304

304 Not Modified is a small header-only reply that tells you the copy you asked about is still the answer. That is the conditional-requests contract: validation decides whether a stored copy is fresh, while http-cache-headers describes two clocks — freshness from the cache headers, and correctness from the validator. A 304 is never an error; it is the cheap way to say “you already have the right bytes”. When the ETag changes, the next revalidation returns a fresh 200.

6. Negotiate a smaller representation when you can

The same content can travel in fewer bytes when the client says it can decompress. Offer gzip and watch the body shrink while the meaning stays identical:

$ curl -s -o /dev/null -w 'no-enc: %{size_download} bytes\n' https://www.xbcatm.com/
$ curl -s -o /dev/null -H 'Accept-Encoding: gzip' -w 'gzip:   %{size_download} bytes\n' https://www.xbcatm.com/
no-enc: 15890 bytes
gzip:   4368 bytes

The plain GET returned 15890 bytes; the gzip negotiation returned 4368 for the same content. That is the http-compression-negotiation note’s core idea: changing the selected representation changes the bytes on the wire, and the metadata (content-length, encoding) changes with it. A client that requests compression and a cache that stores the encoded form must agree on which representation they selected, otherwise the cache serves a mismatch.

7. Follow the story when a URL changes

When identity changes, the response should say where the story continues rather than guess the body:

$ curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' -I http://www.xbcatm.com/ | head -1
308 -> https://www.xbcatm.com/

308 Permanent Redirect keeps the method and preserves the story, which is the concern of redirects-and-status-codes. Whether it is a 301/308 for a permanent move, or a 404 handled by the site, the status line is the first sentence of the story and should be read before the body.

8. Let the crawler read the map last

The edge is also read by machines that do not request HTML at all. Discovery answers two different questions, as robots-and-sitemaps explains. Confirm discovery points at the real sitemap:

$ curl -s https://www.xbcatm.com/robots.txt
User-agent: *
Disallow:
Sitemap: https://www.xbcatm.com/sitemap.xml

A host that answers its own hosts across robots, sitemap, and the HTTP headers is one whose operator has read the public edge before publishing it.

The whole path in one glance

CheckWhat it provesNote
OPTIONS -> 405origin rejects unsupported methodshttp-method-semantics
content-type + nosniffheader names the real bytescontent-type-and-nosniff
HEAD == GET Content-Lengthsafe, head parityhead-parity
Range 0-99 -> 206/100exact byte selectionhttp-range-requests
ETag -> 304validator decides freshnessconditional-requests
308 follows methodredirects preserve the storyredirects-and-status-codes
robots -> sitemapdiscovery answers differrobots-and-sitemaps

Each row was a note; now it is a command you can run against any edge. Read the linked note when you need the details, and keep this table as your re-check before you trust an endpoint.

Sources