HTTP Deep Dive
HTTP/1.0 → HTTP/1.1 → HTTPS → HTTP/2 → HTTP/3 — từng bước tiến hóa, từng bit trong frame. Từ GET / HTTP/1.0 đến QUIC streams trên UDP.
HTTP là gì?
HTTP (HyperText Transfer Protocol) là giao thức tầng ứng dụng (OSI Layer 7) được thiết kế để truyền tải hypermedia — ban đầu là HTML, nay là mọi loại dữ liệu. HTTP chạy trên TCP/IP và hoạt động theo mô hình request-response: client gửi request, server trả response.
HTTP là stateless — mỗi request hoàn toàn độc lập, server không nhớ gì về request trước. Mọi state phải được truyền tường minh qua headers hoặc body. HTTP/1.x là giao thức text-based (human-readable), HTTP/2 và HTTP/3 chuyển sang binary.
- RFC 1945 — HTTP/1.0 (1996)
- RFC 2616 — HTTP/1.1 (1999) → thay bởi RFC 7230-7235 (2014) → RFC 9110-9112 (2022)
- RFC 7540 — HTTP/2 (2015) → RFC 9113 (2022)
- RFC 9114 — HTTP/3 (2022), cùng RFC 9000 (QUIC)
- RFC 9110 — HTTP Semantics (phương thức, status codes, headers — dùng chung cho mọi version)
| Use case | Mô tả | HTTP feature dùng |
|---|---|---|
| Web pages | Tải HTML, CSS, JS, images | GET, caching, conditional requests |
| REST API | CRUD qua JSON/XML | GET/POST/PUT/DELETE/PATCH, status codes |
| File download | Tải file lớn, resume | Range requests, Content-Disposition |
| Server-Sent Events | Server push real-time updates | Chunked transfer, EventStream |
| WebSocket upgrade | Nâng cấp lên full-duplex | Upgrade header, 101 Switching Protocols |
| Webhooks | Server notify client | POST callback |
HTTP/1.0
Ra đời năm 1996 (RFC 1945), HTTP/1.0 là phiên bản chính thức đầu tiên. Mô hình rất đơn giản: mỗi request mở một TCP connection mới, nhận response, rồi đóng kết nối ngay lập tức.
GET /index.html HTTP/1.0 User-Agent: Mozilla/1.0 HTTP/1.0 200 OK Content-Type: text/html Content-Length: 1234 <html>...</html>
- 1 request = 1 TCP connection — mỗi tài nguyên (HTML, CSS, JS, image) cần một TCP 3-way handshake riêng → latency cao
- Không có Host header — 1 IP chỉ host được 1 website (virtual hosting không khả thi)
- Không có persistent connections — mọi request đều có overhead TCP setup/teardown
- Không có chunked encoding — server phải biết Content-Length trước khi bắt đầu gửi
- Không có caching headers chuẩn — các browser phải tự đoán
Một trang web với 30 assets cần 30 TCP connections, mỗi cái tốn ~1 RTT cho handshake. Với mạng 100ms RTT, chỉ riêng handshakes đã mất 3 giây.
HTTP/1.1
RFC 2616 (1997) đưa ra những cải tiến căn bản. HTTP/1.1 là giao thức thống trị web trong hơn 15 năm và vẫn được dùng rộng rãi đến hôm nay.
Persistent Connections (Keep-Alive)
Mặc định trong HTTP/1.1, một TCP connection có thể phục vụ nhiều request/response liên tiếp. Client gửi Connection: keep-alive (hoặc không cần vì đây là default), server trả lời tương tự.
Connection: keep-alive Keep-Alive: timeout=5, max=1000
Pipelining
Client có thể gửi nhiều request mà không cần đợi response của request trước. Tuy nhiên response phải trả về theo đúng thứ tự — đây là nguyên nhân của Head-of-Line (HOL) Blocking: nếu request đầu tiên chậm, tất cả response phía sau bị block dù đã sẵn sàng.
Chunked Transfer Encoding
Server có thể bắt đầu gửi response trước khi biết tổng Content-Length. Mỗi chunk có prefix là kích thước (hex), kết thúc bằng chunk rỗng 0\r\n\r\n.
HTTP/1.1 200 OK Transfer-Encoding: chunked 1a\r\n This is the first chunk\r\n 0e\r\n second chunk!!\r\n 0\r\n \r\n
Host Header (bắt buộc)
HTTP/1.1 yêu cầu Host header trong mọi request — giải quyết vấn đề virtual hosting, nhiều domain trên cùng 1 IP.
HTTP/1.1 giới thiệu If-Modified-Since và If-None-Match để validation cache, giúp server trả 304 Not Modified thay vì gửi lại toàn bộ body.
HTTP Methods & Semantics
Phương thức HTTP mô tả ý định của request. RFC 9110 định nghĩa các thuộc tính ngữ nghĩa quan trọng: safe (không có side effects) và idempotent (gọi nhiều lần = gọi 1 lần).
| Method | Safe | Idempotent | Request Body | Mô tả |
|---|---|---|---|---|
GET | ✓ | ✓ | Không | Lấy tài nguyên |
HEAD | ✓ | ✓ | Không | Như GET nhưng không có body response |
OPTIONS | ✓ | ✓ | Không | Hỏi về capabilities của server/resource (CORS preflight) |
POST | ✗ | ✗ | Có | Tạo resource mới hoặc trigger action |
PUT | ✗ | ✓ | Có | Thay thế toàn bộ resource |
PATCH | ✗ | ✗* | Có | Cập nhật một phần resource |
DELETE | ✗ | ✓ | Thường không | Xóa resource |
CONNECT | ✗ | ✗ | Không | Tạo tunnel TCP (dùng cho HTTPS qua proxy) |
TRACE | ✓ | ✓ | Không | Echo request (debugging, thường bị disable vì XST attack) |
Safe = không thay đổi state server (GET, HEAD, OPTIONS). Client có thể gọi bao nhiêu lần tùy ý. Search engine crawlers chỉ follow safe methods.
Idempotent = gọi N lần = gọi 1 lần về mặt kết quả (GET, PUT, DELETE). Quan trọng cho retry logic — safe to retry sau network failure.
PUT vs PATCH
PUT /users/1 thay thế toàn bộ user 1 bằng body mới — các field không có trong body sẽ bị xóa. PATCH /users/1 chỉ cập nhật các field được chỉ định.
PATCH /users/1 HTTP/1.1
Content-Type: application/merge-patch+json
{"email": "new@example.com"} ← chỉ email thay đổi, các field khác giữ nguyên
HTTP Headers & Message Structure
Một HTTP message gồm 3 phần: start-line, header fields (mỗi cái trên 1 dòng), blank line (CRLF), và body (tuỳ chọn).
Request Headers phổ biến
| Header | Ví dụ | Mô tả |
|---|---|---|
Host | example.com:8080 | Bắt buộc trong HTTP/1.1 — tên domain + port |
Accept | application/json, text/html;q=0.9 | Media types client chấp nhận |
Accept-Encoding | gzip, br, zstd | Compression algorithms client hiểu |
Authorization | Bearer <token> | Credentials để authenticate |
Cookie | session=abc; theme=dark | Cookies gửi lên server |
Content-Type | application/json; charset=utf-8 | Media type của request body |
If-None-Match | "abc123" | Conditional — trả 304 nếu ETag match |
Origin | https://app.example.com | Origin của request (CORS) |
Response Headers phổ biến
| Header | Ví dụ | Mô tả |
|---|---|---|
Content-Type | application/json; charset=utf-8 | Media type của response body |
Content-Encoding | gzip | Compression đã áp dụng |
Cache-Control | max-age=86400, public | Caching directives |
ETag | "33a64df5" | Version identifier của resource |
Location | https://example.com/new | Redirect target (3xx) hoặc URL của resource mới tạo (201) |
Set-Cookie | session=xyz; HttpOnly; Secure | Set cookie trên client |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Force HTTPS (HSTS) |
Access-Control-Allow-Origin | https://app.example.com | CORS — origin được phép |
Status Codes
Status code là số 3 chữ số trong response start-line, truyền đạt kết quả của request. Chữ số đầu tiên xác định nhóm (class). Sau đây là các code phổ biến nhất.
1xx — Informational
| Code | Tên | Mô tả |
|---|---|---|
100 | Continue | Server đã nhận headers, client tiếp tục gửi body |
101 | Switching Protocols | Server chấp nhận upgrade (HTTP → WebSocket) |
2xx — Success
| Code | Tên | Mô tả |
|---|---|---|
200 | OK | Request thành công, response có body |
201 | Created | Resource được tạo, trả về Location header |
202 | Accepted | Request được nhận, xử lý async |
204 | No Content | Thành công, không có body (DELETE, PUT thường dùng) |
206 | Partial Content | Range request — chỉ trả một phần resource |
3xx — Redirection
| Code | Tên | Permanent? | Method preserved? |
|---|---|---|---|
301 | Moved Permanently | ✓ | ✗ (POST → GET) |
302 | Found | ✗ | ✗ (POST → GET) |
303 | See Other | ✗ | Luôn GET |
304 | Not Modified | — | — (cache hit) |
307 | Temporary Redirect | ✗ | ✓ (POST stays POST) |
308 | Permanent Redirect | ✓ | ✓ (POST stays POST) |
4xx — Client Errors
| Code | Tên | Mô tả |
|---|---|---|
400 | Bad Request | Request malformed, syntax sai |
401 | Unauthorized | Chưa authenticate — gửi credentials |
403 | Forbidden | Đã authenticate nhưng không có quyền |
404 | Not Found | Resource không tồn tại |
405 | Method Not Allowed | Method không được phép cho resource này |
409 | Conflict | State conflict (ví dụ: tạo duplicate, optimistic locking) |
422 | Unprocessable Entity | Syntax đúng nhưng semantics sai (validation errors) |
429 | Too Many Requests | Rate limit exceeded — thường có Retry-After header |
5xx — Server Errors
| Code | Tên | Mô tả |
|---|---|---|
500 | Internal Server Error | Lỗi không xác định phía server |
502 | Bad Gateway | Proxy nhận response không hợp lệ từ upstream |
503 | Service Unavailable | Server quá tải hoặc đang maintenance |
504 | Gateway Timeout | Upstream không phản hồi kịp thời |
401 Unauthorized thực ra nghĩa là "unauthenticated" — client chưa gửi credentials hoặc credentials không hợp lệ. Response phải có WWW-Authenticate header.
403 Forbidden nghĩa là "unauthorized" — server biết bạn là ai, nhưng bạn không có quyền. Không cần gửi lại credentials.
URL & Content Negotiation
Cấu trúc URL
URL (Uniform Resource Locator) theo RFC 3986 có cấu trúc phân cấp:
scheme · userinfo · host · port · path · query · fragment
- Scheme (
https): giao thức - Authority (
user:pass@host:port): userinfo hiếm dùng, port mặc định 80/443 - Path (
/v2/users/42): phân cấp bằng/ - Query (
?sort=name&page=2): key=value pairs, phân tách bằng& - Fragment (
#profile): chỉ xử lý ở browser, không gửi lên server
Percent Encoding
Ký tự ngoài "unreserved chars" (A-Z a-z 0-9 -._~) phải được encode thành %XX (hex byte). Ví dụ: space → %20, / trong query → %2F, @ → %40.
Content Negotiation
Client và server thoả thuận format thông qua headers. q-values (quality factor, 0–1) thể hiện độ ưu tiên:
Accept: text/html, application/xhtml+xml, application/json;q=0.9, */*;q=0.8 Accept-Language: vi-VN,vi;q=0.9,en-US;q=0.8,en;q=0.7 Accept-Encoding: br, gzip;q=0.9, zstd;q=0.8, deflate;q=0.5
Server chọn format phù hợp nhất và trả về Content-Type, Content-Language, Content-Encoding.
Nói với CDN/proxy rằng response thay đổi theo những request headers nào: Vary: Accept-Encoding, Accept-Language. CDN sẽ cache riêng biệt cho mỗi combination. Quan trọng để tránh server gzip response cho client không hiểu gzip.
Caching
HTTP caching giúp tránh lấy lại dữ liệu không đổi, giảm latency và tải server. Cache có thể là browser cache, Service Worker, CDN edge, hoặc reverse proxy.
Cache-Control Directives
| Directive | Request / Response | Tác dụng |
|---|---|---|
max-age=N | Cả hai | Resource có thể được cache N giây |
s-maxage=N | Response | Như max-age nhưng chỉ cho shared cache (CDN) |
no-cache | Cả hai | Phải revalidate với server trước khi dùng cache |
no-store | Cả hai | Không được lưu vào cache (sensitive data) |
must-revalidate | Response | Phải revalidate khi stale — không dùng stale response |
stale-while-revalidate=N | Response | Serve stale trong N giây trong khi fetch mới ở background |
stale-if-error=N | Response | Dùng stale nếu server lỗi, trong N giây |
immutable | Response | Resource không bao giờ thay đổi — skip revalidation |
private | Response | Chỉ browser cache, không lưu vào shared cache |
public | Response | Có thể cache ở shared caches (CDN) |
Validation (Conditional Requests)
Khi cache stale, client gửi conditional request để kiểm tra xem resource có thay đổi không:
GET /api/data HTTP/1.1 If-None-Match: "33a64df5" ← ETag từ response trước If-Modified-Since: Sat, 01 Jan 2025 00:00:00 GMT HTTP/1.1 304 Not Modified ← không có body — dùng cache ETag: "33a64df5"
no-cache: có thể lưu cache, nhưng phải revalidate trước khi dùng (conditional request). Nếu server trả 304, dùng bản cached. Tốt cho nội dung thường thay đổi nhưng muốn tận dụng bandwidth saving.
no-store: không lưu gì cả — không có disk cache, không có memory cache. Dùng cho thông tin nhạy cảm (banking, medical).
Cache Layers
Browser Request ↓ miss? Browser Cache (disk/memory) ↓ miss? Service Worker Cache (if registered) ↓ miss? CDN Edge (shared cache, nearest PoP) ↓ miss? Origin Server
Với Cache-Control: max-age=31536000, immutable (1 năm) và content-hash trong filename (app.a3f9c.js), static assets có thể cache vĩnh viễn — đây là kỹ thuật cache busting.
Cookies & Sessions
Cookie là cơ chế chính để HTTP stateless protocol "nhớ" state. Server set cookie qua Set-Cookie header, browser tự động gửi lại trong mọi request đến cùng domain.
Set-Cookie: session_id=abc123xyz; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=3600 Set-Cookie: theme=dark; Path=/; SameSite=Lax; Max-Age=31536000
Cookie Attributes
| Attribute | Tác dụng | Security implication |
|---|---|---|
HttpOnly | JavaScript không đọc được cookie (document.cookie) | Ngăn XSS đánh cắp session cookie |
Secure | Chỉ gửi qua HTTPS | Ngăn sniffing trên HTTP |
SameSite=Strict | Không gửi trong cross-site requests | Bảo vệ tốt nhất chống CSRF |
SameSite=Lax | Gửi trong same-site + top-level navigation GET | Mặc định Chrome, cân bằng security/usability |
SameSite=None | Gửi trong mọi cross-site request | Phải đi kèm Secure — dùng cho third-party cookies |
Domain=.example.com | Chia sẻ cookie cho subdomains | Mở rộng attack surface |
Path=/api | Chỉ gửi cho requests đến /api/* | Giới hạn phạm vi |
Max-Age=N | Sống N giây rồi expire | Không có → session cookie (xóa khi đóng browser) |
Server-side sessions: server lưu session data, cookie chỉ chứa session ID. Dễ invalidate nhưng cần storage (Redis).
JWT (stateless): mọi state encode trong token, server không lưu gì. Dễ scale nhưng khó revoke trước khi expire.
CORS
Same-Origin Policy (SOP) — trình duyệt chặn JavaScript đọc response từ origin khác. Origin = scheme + host + port. https://app.com và https://api.com là cross-origin.
CORS (Cross-Origin Resource Sharing) cho phép server opt-in cho phép cross-origin requests thông qua headers.
Simple Requests vs Preflighted Requests
Simple Request
Method là GET/HEAD/POST và Content-Type là text/plain, multipart/form-data, hoặc application/x-www-form-urlencoded — không cần preflight.
Preflighted Request
Method khác (PUT/DELETE/PATCH), hoặc Content-Type là application/json, hoặc custom headers → browser tự động gửi OPTIONS preflight trước.
OPTIONS /api/data HTTP/1.1 Origin: https://app.example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: Content-Type, Authorization HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://app.example.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization Access-Control-Max-Age: 86400 ← browser cache preflight result 24h
| CORS Header | Direction | Ý nghĩa |
|---|---|---|
Access-Control-Allow-Origin | Response | Origin được phép (hoặc *) |
Access-Control-Allow-Methods | Response | Methods được phép |
Access-Control-Allow-Headers | Response | Request headers được phép |
Access-Control-Allow-Credentials | Response | true nếu cho phép cookies/auth |
Access-Control-Expose-Headers | Response | Response headers JS được đọc |
Access-Control-Max-Age | Response | Cache preflight N giây |
Access-Control-Allow-Origin: * không hoạt động với credentials: 'include' (cookies, HTTP auth). Phải specify exact origin và set Access-Control-Allow-Credentials: true.
HTTPS & PKI
HTTP truyền dữ liệu dạng plaintext — bất kỳ ai ở giữa (ISP, Wi-Fi router, proxy) đều có thể đọc và sửa. HTTPS = HTTP over TLS, cung cấp 3 đảm bảo:
- Confidentiality — dữ liệu được mã hóa, chỉ client và server đọc được
- Integrity — dữ liệu không bị sửa đổi trong quá trình truyền (AEAD)
- Authenticity — client xác minh đang nói chuyện với server đúng (certificate)
X.509 Certificates
Certificate là tài liệu kỹ thuật số chứng minh "public key này thuộc về domain này". Các field chính:
- Subject: CN (Common Name) hoặc SAN (Subject Alternative Names) — domain names
- Issuer: Certificate Authority đã ký
- Validity: NotBefore, NotAfter
- Public Key: RSA hoặc ECDSA public key
- Signature: Issuer ký bằng private key của họ
SAN (Subject Alternative Names) thay thế CN để list nhiều domains: *.example.com, example.com, api.example.com.
CA Chain (Certificate Chain of Trust)
Root CA (self-signed, trong trust store OS/browser)
└─ Intermediate CA (ký bởi Root CA)
└─ Leaf Certificate (ký bởi Intermediate CA)
domain: api.example.com
Trình duyệt không cần biết Leaf cert từ trước — chỉ cần trace chain lên đến một Root CA trong trust store.
Extension của TLS cho phép client gửi domain name trong ClientHello trước khi TLS handshake hoàn thành. Nhờ đó, 1 IP có thể serve nhiều HTTPS websites với certificates khác nhau — giải quyết vấn đề IPv4 exhaustion.
RFC 6962 — mọi certificate phải được log vào ít nhất 2 CT logs công khai trước khi Chrome chấp nhận. SCT (Signed Certificate Timestamp) được nhúng vào cert hoặc gửi qua OCSP/TLS extension. Giúp phát hiện mis-issued certificates.
TLS Handshake
TLS (Transport Layer Security) là giao thức bảo mật chạy giữa TCP và HTTP. TLS 1.3 (RFC 8446, 2018) là phiên bản hiện đại nhất — giảm latency từ 2 RTT (TLS 1.2) xuống còn 1 RTT, và loại bỏ toàn bộ cipher suites không an toàn.
TLS 1.2 vs TLS 1.3
| Khía cạnh | TLS 1.2 | TLS 1.3 |
|---|---|---|
| Handshake RTT | 2 RTT | 1 RTT (0-RTT với resumption) |
| Key exchange | RSA hoặc DHE/ECDHE (negotiated) | ECDHE bắt buộc (PFS luôn on) |
| Cipher suites | ~37 suites (nhiều cái không an toàn) | 5 suites (chỉ AEAD) |
| Certificate encryption | Plaintext trong handshake | Encrypted sau ServerHello |
| Renegotiation | Có (attack surface) | Bỏ |
TLS 1.3 cipher suites: TLS_AES_128_GCM_SHA256 TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_AES_128_CCM_SHA256 TLS_AES_128_CCM_8_SHA256 TLS 1.2 example: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ← key exchange + auth + cipher + hash
Early data (0-RTT) không có forward secrecy cho session ticket, và dễ bị replay attacks — attacker capture và replay early_data. Không nên dùng 0-RTT cho non-idempotent operations (POST, DELETE). Chỉ safe cho idempotent GET.
HTTP/2 — Binary Framing
HTTP/2 (RFC 7540, 2015) thay đổi căn bản cách HTTP truyền dữ liệu: từ text-based sang binary framing. Mọi dữ liệu được đóng gói vào frames — đơn vị truyền tải nhỏ nhất.
Frame Types
| Type | Hex | Mô tả |
|---|---|---|
DATA | 0x0 | Payload của request/response body |
HEADERS | 0x1 | Mở stream + gửi header fields (HPACK-encoded) |
PRIORITY | 0x2 | Stream priority (deprecated RFC 9113) |
RST_STREAM | 0x3 | Cancel stream ngay lập tức |
SETTINGS | 0x4 | Connection parameters (window size, max streams, ...) |
PUSH_PROMISE | 0x5 | Server push announcement |
PING | 0x6 | Keepalive + RTT measurement |
GOAWAY | 0x7 | Graceful shutdown với last stream ID |
WINDOW_UPDATE | 0x8 | Flow control — tăng window size |
CONTINUATION | 0x9 | Header block continuation (HEADERS quá lớn) |
Connection preface (client gửi đầu tiên sau TCP+TLS): PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n SETTINGS frame (empty hoặc với params) Server responds: SETTINGS frame SETTINGS ACK
HTTP/2 — Streams & Multiplexing
Một stream là một luồng request-response độc lập trong cùng một TCP connection. HTTP/2 cho phép hàng trăm streams chạy song song — đây là cải tiến lớn nhất so với HTTP/1.1.
Stream States
idle ──HEADERS──→ open ──END_STREAM──→ half-closed(local)
│ │
└──END_STREAM──→ half-closed(remote) ──END_STREAM──→ closed
│
└──RST_STREAM──→ closed
Stream IDs
- Client-initiated streams: odd IDs (1, 3, 5, …)
- Server-initiated streams (push): even IDs (2, 4, 6, …)
- Stream ID 0: connection-level frames (SETTINGS, PING, GOAWAY)
- IDs không được tái sử dụng — khi hết (tới 2³¹-1), cần mở connection mới
HOL Blocking — HTTP/2 vs HTTP/1.1
HTTP/2 giải quyết HTTP-layer HOL blocking: nhiều requests không còn phải xếp hàng chờ nhau. Tuy nhiên TCP-layer HOL blocking vẫn còn — nếu một TCP packet bị mất, tất cả streams trên connection đó phải đợi retransmit. HTTP/3 (QUIC) mới giải quyết được vấn đề này.
RST_STREAM: cancel một stream cụ thể (ví dụ user cancel download). Connection vẫn hoạt động bình thường.
GOAWAY: thông báo đóng connection, kèm last processed stream ID. Streams có ID cao hơn phải retry trên connection mới.
SETTINGS frame params: HEADER_TABLE_SIZE = 4096 (HPACK dynamic table size) ENABLE_PUSH = 1 (server push on/off) MAX_CONCURRENT_STREAMS = 100 (max parallel streams) INITIAL_WINDOW_SIZE = 65535 (flow control) MAX_FRAME_SIZE = 16384 (max DATA frame size) MAX_HEADER_LIST_SIZE = unlimited
HPACK Header Compression
HTTP/1.1 gửi headers dạng plaintext mỗi request — với cookies và JWT tokens, headers có thể chiếm hàng KB. HPACK (RFC 7541) nén headers xuống còn vài bytes bằng indexing và Huffman coding.
Encoding Types
- Indexed Header Field: header đã có trong static/dynamic table → encode bằng 1 byte (index với prefix bit 1)
- Literal with Incremental Indexing: header mới → encode literal + thêm vào dynamic table cho lần sau
- Literal without Indexing: encode literal, không thêm vào table (ít dùng)
- Literal Never Indexed: encode literal, đánh dấu không bao giờ index — dùng cho
Authorization,Cookieđể ngăn CRIME/BREACH-style attacks
Huffman Coding
HPACK dùng Huffman table tĩnh được xây dựng từ thống kê traffic HTTP/1.1 thực tế. Mỗi byte ASCII được thay bằng bit pattern có độ dài biến thiên. Ký tự phổ biến (như e, a) = ít bits. Trung bình giảm ~30% so với ASCII.
HTTP/2 — Flow Control & Priority
HTTP/2 có cơ chế flow control ở cả cấp stream lẫn connection để ngăn sender làm overwhelm receiver.
Flow Control Windows
Mỗi stream và connection có một receive window (mặc định 65,535 bytes). Sender chỉ được gửi DATA frames trong giới hạn window. Receiver gửi WINDOW_UPDATE để tăng window khi đã xử lý xong dữ liệu.
WINDOW_UPDATE frame: Stream ID: 0 (connection-level) Window Size Increment: 1048576 (tăng thêm 1 MB)
Priority (RFC 7540 — deprecated)
RFC 7540 định nghĩa dependency tree với weight (1–256). Tuy nhiên việc implement phức tạp và dễ gây priority inversion. RFC 9113 loại bỏ hoàn toàn, thay bằng Extensible Priorities (RFC 9218).
Thay thế priority tree bằng model đơn giản hơn: urgency (0–7, mặc định 3) và incremental flag. Gửi qua Priority header hoặc PRIORITY_UPDATE frame.
Priority: u=1, i ← urgency=1 (high), incremental=true
SETTINGS_INITIAL_WINDOW_SIZE ảnh hưởng đến initial window của tất cả streams mới được tạo sau SETTINGS frame đó — không ảnh hưởng retroactively đến streams hiện tại.
Security Headers
Ngoài TLS, HTTP cung cấp nhiều response headers để hardening bảo mật browser-side.
| Header | Ví dụ giá trị | Bảo vệ chống |
|---|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | SSL stripping, HTTP downgrade |
Content-Security-Policy | default-src 'self'; script-src 'nonce-xxx' | XSS, data injection, clickjacking |
X-Frame-Options | DENY hoặc SAMEORIGIN | Clickjacking (legacy, dùng CSP frame-ancestors) |
X-Content-Type-Options | nosniff | MIME-type sniffing attacks |
Referrer-Policy | strict-origin-when-cross-origin | Rò rỉ URL trong Referer header |
Permissions-Policy | camera=(), microphone=(), geolocation=(self) | Lạm dụng browser APIs |
Cross-Origin-Opener-Policy | same-origin | Cross-origin window attacks (Spectre) |
Cross-Origin-Embedder-Policy | require-corp | SharedArrayBuffer leaks (Spectre) |
Cross-Origin-Resource-Policy | same-origin | Cross-origin resource embedding |
HSTS Preload
Ngoài HSTS header, bạn có thể submit domain vào Chromium preload list (hstspreload.org) — browser sẽ không bao giờ kết nối HTTP đến domain này, ngay cả lần đầu tiên. Yêu cầu: max-age ≥ 31536000, includeSubDomains, preload. Cực kỳ khó revoke.
Content Security Policy
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0m' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' wss://api.example.com; frame-ancestors 'none'; report-uri /csp-report
unsafe-inlinetrong script-src phủ nhận hầu hết lợi ích của CSP- Dùng nonce-based hoặc hash-based CSP thay vì unsafe-inline
report-uri(deprecated) → dùngreport-tovới Reporting API
HTTP/3 & QUIC
HTTP/3 (RFC 9114, 2022) chạy trên QUIC (RFC 9000) thay vì TCP. QUIC là giao thức transport mới, được implement trong user-space (không phải kernel), chạy trên UDP.
QUIC Features
- Independent stream multiplexing: mất packet trên stream 1 không block stream 2 — TCP HOL blocking biến mất
- 0-RTT connection: với session resumption, application data được gửi ngay trong first packet
- Connection migration: Connection ID (không phải IP:port) định danh connection — di chuyển từ 4G sang WiFi mà không reset connection
- TLS 1.3 integrated: không cần separate TLS handshake — QUIC crypto handshake và transport handshake chạy song song
- User-space implementation: dễ iterate, không cần kernel update
HTTP/3 vs HTTP/2
HTTP/3 giữ nguyên HTTP semantics (methods, status codes, headers) nhưng thay đổi transport layer:
- HPACK → QPACK: QPACK (RFC 9204) là phiên bản HPACK được thiết kế cho QUIC — xử lý out-of-order delivery
- Server Push deprecated: HTTP/3 vẫn có push nhưng các browsers đã disable (Chrome 106+)
- Priority tree → Extensible Priorities (RFC 9218)
| Tính năng | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| Transport | TCP | TCP | QUIC (UDP) |
| Handshake | TCP + TLS = 2 RTT | TCP + TLS = 2 RTT | QUIC = 1 RTT (0-RTT resume) |
| Multiplexing | Pipelining (HOL) | Streams (TCP HOL) | Streams (no HOL) |
| Header compression | Không | HPACK | QPACK |
| Connection migration | ✗ | ✗ | ✓ (Connection ID) |
| Server push | ✗ | ✓ (deprecated) | ✓ (browsers disabled) |
| Adoption (2024) | ~30% | ~40% | ~30% |
Các điểm cốt lõi cần nhớ
Những điểm quan trọng nhất từ 18 sections — hay bị nhầm, hay gặp trong interviews, hay phát sinh bug trong production.
HTTP Evolution
- HTTP/1.0: 1 TCP/request, không Host header, không persistent connection
- HTTP/1.1: keep-alive, chunked transfer, Host bắt buộc, pipelining (nhưng HOL blocking)
- HTTP/2: binary frames, multiplexing, HPACK — fixes HTTP-layer HOL; TCP-layer HOL vẫn còn
- HTTP/3: QUIC + UDP, 1-RTT, no HOL cả transport, connection migration qua Connection ID
Methods & Status Codes
- Safe (không side-effect): GET, HEAD, OPTIONS
- Idempotent (gọi N lần = 1 lần): GET, PUT, DELETE — POST không idempotent
- 301 redirect → đổi method sang GET; 308 → giữ nguyên method
- 401 = chưa authenticate; 403 = đã auth nhưng không có quyền
- 429 Too Many Requests — 503 Service Unavailable (khác nhau về retry)
Caching
- no-cache ≠ không cache — vẫn cache nhưng phải revalidate mỗi lần
- no-store = không lưu gì cả (dùng cho sensitive data)
- immutable = không bao giờ revalidate (content-hashed assets: bundle.abc123.js)
- ETag + If-None-Match → 304 Not Modified (tiết kiệm bandwidth)
- stale-while-revalidate: serve stale ngay, fetch mới trong nền
HTTPS & TLS 1.3
- TLS 1.3: 1-RTT (TLS 1.2 = 2-RTT), chỉ 5 cipher suites — tất cả AEAD
- ECDHE bắt buộc → Perfect Forward Secrecy (session key ≠ private key server)
- SNI: client gửi hostname trong ClientHello → server chọn đúng cert
- 0-RTT = nhanh nhưng có replay attack risk → chỉ dùng cho idempotent ops
- Certificate chain: leaf → intermediate → root CA; browser trust root CA store
CORS & Cookies
- SameSite=Lax (default): gửi cookie với top-level GET navigation, không gửi fetch/XHR cross-origin
- SameSite=None bắt buộc có Secure (HTTPS only)
- Preflight OPTIONS kích hoạt khi method/header không thuộc "safe list"
credentials: true+Allow-Origin: *= không hoạt động — phải specify origin cụ thể- HttpOnly: JS không đọc được (chống XSS); Secure: chỉ gửi qua HTTPS
HTTP/2 Internals
- Frame header = 9 bytes: length (3B) + type (1B) + flags (1B) + stream ID (4B)
- HPACK: static table 61 entries, dynamic table FIFO per-connection, Never Indexed cho Authorization
- Stream ID: client = lẻ (1,3,5…), server = chẵn; max concurrent =
SETTINGS_MAX_CONCURRENT_STREAMS - Flow control default = 65,535 bytes/stream và /connection — tăng bằng WINDOW_UPDATE
- PUSH_PROMISE: server push bị disable trên Chrome 106+ và deprecated trong HTTP/3
- HTTP/1.1 pipelining vs HTTP/2 multiplexing? — Pipelining vẫn FIFO (HOL blocking), multiplexing thực sự song song trên cùng connection
- Tại sao HTTP/3 dùng UDP? — Để tránh TCP-level HOL blocking; QUIC implement reliability + ordering ở user-space per-stream
- HPACK Never Indexed dùng khi nào? — Header chứa sensitive value (Authorization, Cookie) không nên vào dynamic table tránh CRIME/BREACH attack
- Khác nhau giữa 401 và 403? — 401 = chưa có credentials (cần login); 403 = có credentials nhưng không đủ quyền
- Tại sao no-cache không có nghĩa là không cache? —
no-cache= "cache nhưng validate với server trước khi dùng";no-store= không lưu gì