HTTP cheat sheet
A scannable HTTP reference: 28 short snippets across 13 topics, each linking back to the lesson it came from.
At a glance
| Topic | What it covers | |
|---|---|---|
| HTTP methods | Idempotent means repeating it has the same effect as doing it once — sending the same DELETE twice should leave things | lesson |
| HTTP status codes | The class is the part a client should branch on. Only the first digit is semantic; the other two are a label. That is | lesson |
| HTTP headers | Content negotiation, auth, compression and security headers — the metadata that controls real behaviour | lesson |
| Caching and conditional requests | Once a response goes stale, the client asks 'has this changed?' rather than downloading it again. Confirmation costs a | lesson |
| CORS explained | Your browser attaches cookies and tokens to requests automatically. Without protection, any site you visited could read | lesson |
| HTTPS and TLS | Note what it does not do: HTTPS does not make a site trustworthy, and it encrypts only the transport — the server still | lesson |
| Message anatomy and framing | Every HTTP exchange is two messages with the same skeleton: a start line, header fields, one empty line, and an | lesson |
| Cookies, sessions and state | HTTP is stateless: each request stands alone. Cookies are the mechanism that lets a server recognise the same client | lesson |
| Authentication on the wire | The WWW-Authenticate header is what turns a 401 into a usable protocol: it names the scheme and its parameters, so a | lesson |
| Compression, content negotiation and media types | Accept and Accept-Encoding with quality values, gzip, Brotli and zstd, charset handling, multipart uploads, and | lesson |
| Proxies, load balancers and connection management | Once a request passes through anything — CDN, load balancer, service mesh, corporate proxy — the connection the server | lesson |
| HTTP API design in practice | Applying method semantics, pagination strategies, ETags in APIs, problem-detail error bodies, versioning, webhooks and | lesson |
| Debugging HTTP: tools, logs and observability | curl and API clients, browser network panel analysis, HAR capture, server access logs, tracing and correlation headers | lesson |
Quick snippets
HTTP methods
PUT vs PATCH vs POST
PUT /users/42
{ "name": "Ada", "email": "[email protected]", "role": "admin" }
// replaces the whole record - omitted fields may be cleared
PATCH /users/42
{ "role": "admin" }
// modifies only the fields provided
POST /users
{ "name": "Ada" }
// creates something new; server assigns the id
HTTP status codes
The five classes
HTTP/1.1 404 Not Found
Content-Type: application/problem+json
Cache-Control: no-store
{
"type": "https://example.com/errors/not-found",
"title": "No such article",
"status": 404,
"detail": "Article 8f2c was deleted on 2026-08-01."
}Full lesson: HTTP status codes →
HTTP headers
Security headers worth setting
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=()
X-Frame-Options: DENY (or CSP frame-ancestors)
Caching and conditional requests
Controlling freshness
Cache-Control: max-age=3600, public
Cache-Control: no-store # never keep it (sensitive data)
Cache-Control: no-cache # store, but revalidate every time
Cache-Control: private, max-age=600
Cache-Control: immutable, max-age=31536000 # fingerprinted assets
Conditional requests
# first response
HTTP/1.1 200 OK
ETag: "a1b2c3"
Cache-Control: max-age=0, must-revalidate
# later request
GET /api/profile HTTP/1.1
If-None-Match: "a1b2c3"
# unchanged response - no body transmitted
HTTP/1.1 304 Not ModifiedFull lesson: Caching and conditional requests →
CORS explained
Simple requests vs preflight
OPTIONS /api/item HTTP/1.1
Origin: https://app.example
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: authorization
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: authorization
Access-Control-Max-Age: 600
Fixing it in practice
// Express: allow one trusted app
app.use(cors({
origin: 'https://app.example',
credentials: true
}));
// fetch side: include cookies when needed
fetch(url, { credentials: 'include' });
HTTPS and TLS
Certificate chains
openssl s_client -connect example.com:443 -servername example.com
echo | openssl s_client -connect example.com:443 2>/dev/null \
| openssl x509 -noout -dates -subject -issuer
Renewal without drama
# Let's Encrypt with Certbot
certbot certonly --webroot -w /var/www/app -d example.com -d www.example.com
certbot renew --dry-run
# certificates typically last 90 days; automate renewal
systemctl list-timers | grep certbot
Mixed content
<!-- do not hardcode the scheme -->
<script src='//cdn.example/lib.js'></script>
<!-- better: same-origin, scheme-relative as fallback -->
<script src='/vendor/lib.js'></script>
Message anatomy and framing
The shape of a message
POST /api/orders?dry=1 HTTP/1.1
Host: api.example.com
Content-Type: application/json; charset=utf-8
Content-Length: 27
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.abc
{"sku":"A-1","qty":2}
The shape of a message
HTTP/1.1 201 Created
Location: /api/orders/1042
Content-Type: application/json; charset=utf-8
Content-Length: 62
{"id":1042,"sku":"A-1","qty":2,"status":"pending"}
HTTP/1.1, HTTP/2 and HTTP/3 on the wire
curl -sS -v --http2 https://example.com/ -o /dev/null 2>&1 | grep -iE 'ALPN|using HTTP'
curl -sSI --http3 https://cloudflare.com/ | head -n 1 # needs a curl built with HTTP/3Full lesson: Message anatomy and framing →
Cookies, sessions and state
Set-Cookie and its attributes
HTTP/1.1 200 OK
Set-Cookie: sid=8f3c1a...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=604800
Set-Cookie: theme=dark; Path=/; Max-Age=31536000; SameSite=Lax
Session identifiers
GET /dashboard HTTP/1.1
Host: app.example.com
Cookie: sid=8f3c1a...; theme=dark
If-None-Match: "v7"Full lesson: Cookies, sessions and state →
Authentication on the wire
Challenge and response
GET /admin HTTP/1.1
Host: app.example.com
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="admin", charset="UTF-8"
GET /admin HTTP/1.1
Host: app.example.com
Authorization: Basic YWRhOnMzY3JldA==
Bearer tokens, JWTs and API keys
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImtmMSJ9.eyJzdWIiOiJ1c2VyLTQyIiwiYXVkIjoiYXBpLmV4YW1wbGUuY29tIiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5leGFtcGxlLmNvbSIsImV4cCI6MTc3MDAwMDAwMCwic2NvcGUiOiJvcmRlcnM6cmVhZCJ9.signature
OAuth 2.1, scopes and mutual TLS
GET /authorize?response_type=code&client_id=app123&
redirect_uri=https://app.example/cb&scope=orders:read%20orders:write&
state=x8f2...&code_challenge=E9Melhoa...&code_challenge_method=S256 HTTP/1.1
POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlO&code_verifier=dBjftJeZ...Full lesson: Authentication on the wire →
Compression, content negotiation and media types
Negotiating the representation
GET /report HTTP/1.1
Host: api.example.com
Accept: text/html, application/json;q=0.9, */*;q=0.1
Accept-Language: en-GB, en;q=0.8, fr;q=0.5
Accept-Charset: utf-8
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Language: en
Vary: Accept, Accept-Language
Compression in practice
GET /app.js HTTP/1.1
Accept-Encoding: br, gzip, zstd;q=0.9, identity;q=0.1
HTTP/1.1 200 OK
Content-Type: application/javascript; charset=utf-8
Content-Encoding: br
Vary: Accept-Encoding
Content-Length: 41230
Compression in practice
# pre-compress static assets at build time, then serve by name
brotli -q 11 -k app.js # produces app.js.br
gzip -9 -k app.js # produces app.js.gz
# verify what a server actually sent
curl -sS -o /dev/null -H 'Accept-Encoding: br,gzip' -w '%{size_download} %{content_type}\n' https://example.com/app.js
curl -sSI -H 'Accept-Encoding: br,gzip' https://example.com/app.js | grep -iE 'content-encoding|vary'Full lesson: Compression, content negotiation and media types →
Proxies, load balancers and connection management
What an intermediary changes
GET /api/me HTTP/1.1
Host: app.example.com
Forwarded: for=203.0.113.7;proto=https;host=app.example.com
X-Forwarded-For: 203.0.113.7, 10.0.0.5
X-Forwarded-Proto: https
X-Forwarded-Host: app.example.com
X-Request-Id: 01J8Y7Q2ZK3M4N5P6R7S8T9V0W
Keep-alive, pooling and timeouts
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 82
Connection: keep-alive
Keep-Alive: timeout=5, max=100Full lesson: Proxies, load balancers and connection management →
HTTP API design in practice
Conditional writes, errors and versioning
HTTP/1.1 409 Conflict
Content-Type: application/problem+json
{
"type": "https://api.example.com/problems/out-of-stock",
"title": "Out of stock",
"status": 409,
"detail": "SKU A-1 has 0 units available.",
"errors": [ { "field": "qty", "issue": "exceeds_available" } ]
}
Webhooks and delivery guarantees
POST /hooks/orders HTTP/1.1
Host: consumer.example.com
Content-Type: application/json
X-Event-Id: 01J8Y7Q2ZK3M4N5P6R7S8T9V0W
X-Event-Timestamp: 1770000000
X-Signature: t=1770000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
{"type":"order.shipped","data":{"id":1042,"status":"shipped"}}
Webhooks and delivery guarantees
import crypto from 'node:crypto';
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map(p => p.trim().split('=')));
const age = Math.abs(Date.now() / 1000 - Number(parts.t));
if (age > toleranceSeconds) return false;
const expected = crypto.createHmac('sha256', secret)
.update(parts.t + '.' + rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Full lesson: HTTP API design in practice →
Debugging HTTP: tools, logs and observability
HAR capture, logs and tracing
HTTP/1.1 200 OK
Traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
Server-Timing: db;dur=53.2, cache;desc="MISS";dur=1.7, app;dur=12.4
X-Request-Id: 01J8Y7Q2ZK3M4N5P6R7S8T9V0W
HAR capture, logs and tracing
203.0.113.7 - - [18/Sep/2026:10:04:11 +0000] "GET /v1/orders?limit=50 HTTP/1.1" 200 1843 0.042 "https://app.example.com/" "Mozilla/5.0" rid=01J8Y7Q2ZK3M4N5P6R7S8T9V0W u=user-42Full lesson: Debugging HTTP: tools, logs and observability →
FAQ
Is this HTTP cheat sheet free to use?
Where do the examples come from?
How do I go deeper than a cheat sheet?
Related cheat sheets
Node.js PHP Java Go Rust Spring Boot
Last refreshed 2026-09-27.