C
Network/HTTP/Lesson 04

HTTP — Methods, Status Codes, Headers, HTTPS, TLS, HTTP/2 & 3

45 min·theory

HTTP — Methods, Status Codes, Headers, HTTPS, TLS, HTTP/2 & 3

🎯 What you'll be able to do after this lesson

After finishing this lesson, you'll be able to confidently do the following three things.

  • ✅ Core changes across HTTP 1.0 → 1.1 → 2 → 3
  • ✅ Idempotency of GET, POST, PUT, DELETE, and PATCH
  • ✅ How Cache-Control, ETag, and 304 caching work

Keep the learning objectives as a checklist, and close the lesson once you can answer all of them.

HTTP Methods, Status Codes, and Headers

HTTP Methods (8 total):

MethodMeaningIdempotent?Safe?
GETRetrieve
HEADHeaders only
POSTCreate
PUTFull replace
PATCHPartial update❌ (usually)
DELETEDelete
OPTIONSList allowed methods (CORS preflight)
TRACE·CONNECTDebug·Tunnel

Idempotency = sending the same request N times has the same effect as sending it once. Outside of payments and POST, all methods should be idempotent.


HTTP Status Codes (5 groups):

CodeMeaningExample
1xxInformational100 Continue (OK to send request body)
2xxSuccess200 OK · 201 Created · 204 No Content
3xxRedirect301 Permanent · 302 Temporary · 304 Not Modified (cache)
4xxClient Error400 Bad Request · 401 Unauthorized · 403 Forbidden · 404 Not Found · 409 Conflict · 422 Unprocessable · 429 Too Many Requests
5xxServer Error500 Internal · 502 Bad Gateway · 503 Service Unavailable · 504 Gateway Timeout

Common points of confusion:

  • 401 = Not authenticated (login required)
  • 403 = Authenticated but not authorized
  • 404 = Resource not found (or hidden for authorization purposes)

Key HTTP Headers:

HeaderPurpose
Authorization: Bearer xxxAuthentication token
Content-Type: application/jsonBody format
Accept: application/jsonPreferred response format
Cache-Control: max-age=3600Cache policy
Cookie: session=xxxCookie
User-Agent: Mozilla...Client information
Origin: https://a.comRequest origin (CORS)
X-Forwarded-For: 1.2.3.4Real IP behind proxy
Strict-Transport-SecurityHSTS (force HTTPS)
Content-Security-PolicyCSP (XSS defense)

HTTPS + TLS 1.3 Handshake

HTTPS = HTTP + TLS. Plain HTTP exposes all content if packets are intercepted.

TLS 1.3 Handshake (1-RTT, standardized in 2018):

code
Client                                Server
  │  ── Client Hello (supported algorithms) ──▶  │
  │                                       │
  │  ◀── Server Hello + Certificate          │
  │      + Key Exchange Info                   │
  │                                       │
  │     [Client verifies certificate]         │
  │                                       │
  │  ── Finished (start encryption)        ──▶ │
  │  ◀── Finished                       │
  │                                       │
  │     [Encrypted HTTP communication]              │

3-Step Certificate Validation:
1. Trust: Is the issuer a trusted CA? (browser's built-in CA list)
2. Validity: Not expired? Not revoked (CRL/OCSP)?
3. Match: Does the domain match? (*.example.comapi.example.com)

Forward Secrecy (required in TLS 1.3):

  • Generates a new key each session
  • Even if the server key is compromised, past traffic cannot be decrypted

HTTP/1.1 vs 2 vs 3:

VersionReleaseHighlights
HTTP/1.01996New TCP connection per request
HTTP/1.11997Keep-Alive, pipelining, chunked transfer
HTTP/22015Multiplexing, header compression (HPACK), server push
HTTP/32022 (RFC 9114)QUIC (UDP)-based, 0-RTT

HTTP/2 Multiplexing — multiple streams over a single TCP connection:

  • HTTP/1.1: only 6 concurrent connections (browser limit)
  • HTTP/2: unlimited streams on 1 connection. Solves Head-of-Line blocking

HTTP/3 (QUIC) — overcomes TCP limitations:

  • Solves TCP Head-of-Line blocking (one lost packet blocks everything)
  • 0-RTT reconnection (PSK)
  • Maintains connection across mobile IP changes
💻 📌 Debugging HTTP with curl
# === Basic ===
curl https://api.example.com/users        # GET
curl -i https://api.example.com           # Include headers
curl -v https://api.example.com           # Verbose (up to TLS handshake)
curl -I https://api.example.com           # HEAD (headers only)
curl -L https://example.com               # Follow redirects

# === POST + JSON ===
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Hong Gil-dong","email":"[email protected]"}'

# === Authentication ===
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/me
curl -u user:pass https://api.example.com/secret      # Basic Auth
curl --cookie "session=abc" https://api.example.com   # Cookie

# === Files ===
curl -O https://example.com/file.zip      # Save with that name
curl -o out.json https://api.example.com  # Specified name
curl -F "[email protected]" https://upload.example.com  # Upload

# === Check HTTP/2·3 ===
curl --http2 -I https://example.com       # Force HTTP/2
curl --http3 -I https://cloudflare.com    # HTTP/3 (if supported)

# === TLS Debugging ===
openssl s_client -connect example.com:443 -servername example.com
# Output certificate chain
curl -vI https://example.com 2>&1 | grep -E "subject|issuer"

# === Measure Response Time ===
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://example.com

# === Check HTTP Status (useful in CI) ===
curl -o /dev/null -s -w "%{\n" https://api.example.com/health
# Output only 200 / 404 / 500

HTTP Caching — Cache-Control, ETag, and 304

Why caching matters

Don't re-fetch the same resource every time — it improves bandwidth, server load, and perceived performance.

Cache-Control — the modern standard

code
Cache-Control: public, max-age=3600
Cache-Control: private, max-age=0, no-cache
Cache-Control: public, max-age=31536000, immutable

6 commonly used directives

DirectiveMeaning
publicCan be stored by any cache (including CDN)
privateBrowser-only storage (not CDN)
max-age=NFresh for N seconds
no-cacheMust revalidate with server before use (still cached)
no-storeNever store (login, payments)
immutableNever changes — no revalidation requests either

Real-world patterns

code
# HTML page (code changes frequently)
Cache-Control: no-cache

# JS/CSS bundles (filename includes hash)
Cache-Control: public, max-age=31536000, immutable

# API responses (per-user)
Cache-Control: private, max-age=60

# Login/payment
Cache-Control: no-store

ETag — a fingerprint to check for changes

code
# First request
GET /img.png
→ 200 OK
  ETag: "abc123"
  (image body)

# Second request
GET /img.png
  If-None-Match: "abc123"
→ 304 Not Modified    (no body — use the cached version)

If the ETag matches, no body is sent — saving bandwidth. 1 MB body → 0 KB response.

Last-Modified — the old way

code
Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT
If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT

Less precise than ETag (second-level granularity). Modern servers prefer ETag.

Browser Cache vs CDN Cache

code
[Browser] ↔ [CDN (Cloudflare, etc.)] ↔ [Origin Server]
  • Browser cache: stores private or public. Your machine only.
  • CDN cache: stores public only. Shared across global edge servers.

Use the Vary header to specify which request differences should produce separate cache entries:

code
Cache-Control: public, max-age=3600
Vary: Accept-Encoding, Cookie

stale-while-revalidate — zero latency + freshness

code
Cache-Control: max-age=60, stale-while-revalidate=300

Fresh for the first 60 seconds. From 60–360 seconds, serve the stale response immediately and revalidate in the background. The user gets an instant response, and the next request gets fresh data.

Next.js and TanStack Query use this strategy internally.

🤖 Try asking AI

  • "Set up next.config.js in Next.js to cache static files for 1 year and set no-cache for HTML"
  • "Add a 60-second cache + stale-while-revalidate 300 header to this API response"
HTTP — Methods·Status Codes·Headers·HTTPS·HTTP/2·3 - Network