HTTP is the text-based protocol browsers and servers use on the World Wide Web to exchange HTML, images, and API responses. It runs over TCP (over QUIC = UDP in HTTP/3), and layers a request / response structure on top. HTTPS wraps the same exchange in TLS, defending against eavesdropping, tampering, and impersonation at once. This article walks through message structure, methods, status codes, headers, cookies, the HTTP/1.x → HTTP/3 evolution, the TLS handshake, and the classic security pitfalls.
The basic shape of HTTP #
HTTP is a stateless request / response protocol. The client sends a request, the server sends back a response, and one such round trip is called an HTTP transaction. By default the server keeps no memory of past requests (= stateless). To carry state across requests you layer on cookies, sessions, JWTs, and so on.
The wire format is a text-based HTTP message in four blocks: request-line / status-line → headers → blank line → body. From HTTP/2 onward the bytes are split into binary frames, but the logical structure is the same.
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,*/*
Cookie: session=abc123
# ↑ blank line, then the body (empty for GET)- Request line — method (
GET) / path (/index.html) / protocol version (HTTP/1.1) - Headers —
Name: Valuepairs, one per line.Host/User-Agent/Accept/Cookie/Authorizationand so on - Blank line — the boundary between headers and body
- Body — the data payload sent by
POST/PUTetc (forms / JSON)
HTTP/1.1 200 OK
Date: Sun, 17 May 2026 00:00:00 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax
# ↓ blank line, then the body
<html>
...
</html>Send one yourself — enter a method and path, and the server returns a response with the matching status code. /admin returns 403, an unknown path returns 404, and /old returns 301.
HTTP methods #
| Method | Purpose | Body | Idempotent |
|---|---|---|---|
| GET | Retrieve a resource | None | Yes |
| POST | Create / arbitrary action | Yes | No |
| PUT | Replace the entire resource | Yes | Yes |
| PATCH | Partially update the resource | Yes | No |
| DELETE | Delete the resource | Optional | Yes |
| HEAD | Headers only (metadata version of GET) |
None | Yes |
| OPTIONS | Query supported methods (heavily used in CORS preflight) | None | Yes |
An idempotent method has the property that "sending the same request multiple times produces the same result", which makes safe retry on network failure possible. POST is not idempotent, so it needs explicit double-submit prevention — an Idempotency Key header, disabling the button on the UI, etc.
Status codes #
Three-digit numbers, where the first digit indicates the category.
| Class | Meaning | Examples |
|---|---|---|
| 1xx | Informational | 100 Continue / 101 Switching Protocols |
| 2xx | Success | 200 OK / 201 Created / 204 No Content |
| 3xx | Redirect | 301 Moved Permanently / 302 Found / 304 Not Modified |
| 4xx | Client error | 400 Bad Request / 401 Unauthorized / 403 Forbidden / 404 Not Found / 429 Too Many Requests |
| 5xx | Server error | 500 Internal Server Error / 502 Bad Gateway / 503 Service Unavailable / 504 Gateway Timeout |
401 Unauthorized means "not authenticated" (= please log in). 403 Forbidden means "authenticated but lacking permission" (= even logging in won't help). Some API designs deliberately return 404 in place of 403 to hide the existence of the resource entirely.
Important HTTP headers #
Headers that directly affect security and performance.
Request side:
Host— Virtual host selection. Lets a single IP serve multiple domainsUser-Agent— Client identification. Used as signal by WAFs and bot detectionCookie— Sends back values previously issued bySet-Cookie, on every requestAuthorization— Auth credentials likeBasic/Bearer <token>Referer— URL of the previous page (the misspelling is enshrined in the spec)
Response side:
Set-Cookie— Issue a cookie to the clientContent-Type— MIME type (e.g.application/json; charset=UTF-8)Cache-Control— Cache behavior (no-store/max-age=3600)Strict-Transport-Security(HSTS) — Force HTTPS on subsequent visitsContent-Security-Policy(CSP) — Restrict script sources to mitigate XSSX-Frame-Options/CSP: frame-ancestors— Clickjacking defense
Cookies and sessions #
Because HTTP is stateless, login state and so on are kept in cookies. The server issues them via Set-Cookie, and the client returns them in the Cookie header on every subsequent request.
To prevent session hijacking, modern cookies should always carry the following attributes.
| Attribute | Meaning |
|---|---|
Secure |
Sent only over HTTPS. Never over plain HTTP |
HttpOnly |
Inaccessible from JavaScript's document.cookie. Harder to steal via XSS |
SameSite=Lax / Strict |
Not sent on cross-origin requests. Defends against CSRF |
Expires / Max-Age |
Controls whether it's a session cookie or persistent cookie |
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax; Max-Age=3600; Path=/
# Secure → HTTPS only
# HttpOnly → not readable from JS (XSS mitigation)
# SameSite=Lax → not auto-sent cross-origin (CSRF mitigation)HTTP version evolution #
| Version | Year | Key feature |
|---|---|---|
| HTTP/1.0 | 1996 | One TCP connection per request (heavyweight) |
| HTTP/1.1 | 1997 | Keep-Alive for connection reuse, pipelining (limited practical use) |
| HTTP/2 | 2015 | Binary frames, multiplexing for parallel requests on a single connection, header compression (HPACK) |
| HTTP/3 | 2022 | QUIC (over UDP) for minimal handshake; eliminates head-of-line blocking under packet loss |
In HTTP/1.1, requests queue up and stall behind earlier ones. HTTP/2 mitigated the application-layer HoL with multiplexing, but TCP's ordering guarantees mean a single dropped packet still stalls every later one — a transport-layer HoL. HTTP/3 resolves the transport-layer HoL too by implementing independent streams on top of UDP through QUIC.
HTTPS and the TLS handshake #
HTTPS = HTTP + TLS (Transport Layer Security). TLS achieves three things at once.
- Encryption — Hide content from third parties (confidentiality)
- Tamper detection — Detect content modification via MAC (integrity)
- Server authentication — Confirm the server is who it claims to be, via certificate (authenticity)
The TLS 1.3 handshake completes in four steps.
TLS 1.2 needed two round trips; TLS 1.3 takes only one (1-RTT), and 0-RTT for resumed sessions.
The server certificate is issued by a Certificate Authority (CA). The client verifies the chain (server certificate → intermediate CA → root CA) against the root CA public keys bundled with the OS / browser, and only completes the TLS connection if it validates.
| Type | What is verified | Examples |
|---|---|---|
| DV (Domain Validation) | Domain ownership only | Let's Encrypt and other free issuers |
| OV (Organization Validation) | Organization existence as well | Major commercial CAs |
| EV (Extended Validation) | Stricter organization verification | The legacy green address bar is now retired |
Security pitfalls #
Common pitfalls from a server-admin / developer perspective.
- MITM (man-in-the-middle) — Attacker sits on the path (e.g. on public Wi-Fi) and intercepts / modifies requests. HTTPS with proper certificate verification stops this
- SSL Stripping — An attacker blocks the HTTPS redirect and downgrades the user to plain HTTP. HSTS (
Strict-Transport-Security) forces the browser to use HTTPS on later visits - HSTS Preload — Registering a domain in the preload list shipped with Chrome / Firefox forces HTTPS even on the very first visit
- Mixed Content — An HTTPS page loading HTTP resources (images / scripts) breaks the TLS guarantee. The
upgrade-insecure-requestsCSP directive forces them to HTTPS - Missing cookie attributes — Forgetting
Secure/HttpOnly/SameSiteexposes you to session hijacking / XSS / CSRF - The pitfall of certificate pinning — Pinning too aggressively means broken connections on CA rotation. HPKP (HTTP Public Key Pinning) has been deprecated
- TLS implementation bugs — Heartbleed (CVE-2014-0160) and others. Keeping OpenSSL current is a baseline defense
Pentests routinely use Burp Suite or mitmproxy with a local CA to decrypt TLS traffic and inspect it. This is fundamentally "temporarily disabling certificate validation" and must never be done in production. Use it only in dedicated test VMs / isolated environments, and remove the local CA from the system when you're done.