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/1.0 1996 · RFC 1945 HTTP/1.1 1997 · RFC 7230 HTTPS / TLS 2000s · RFC 2818 HTTP/2 2015 · RFC 7540 HTTP/3 2022 · RFC 9114
01

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 Overview
  • 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 caseMô tảHTTP feature dùng
Web pagesTải HTML, CSS, JS, imagesGET, caching, conditional requests
REST APICRUD qua JSON/XMLGET/POST/PUT/DELETE/PATCH, status codes
File downloadTải file lớn, resumeRange requests, Content-Disposition
Server-Sent EventsServer push real-time updatesChunked transfer, EventStream
WebSocket upgradeNâng cấp lên full-duplexUpgrade header, 101 Switching Protocols
WebhooksServer notify clientPOST callback
02

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>
Vấn đề của HTTP/1.0
  • 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.

03

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.0 New conn per request HTTP/1.1 Keep-Alive Serial (HOL blocking) HTTP/2 Parallel streams TCP conn → REQ1 → RESP1 → close TCP conn → REQ2 → RESP2 → close TCP conn → REQ3 → RESP3 → close 3× TCP handshakes 1 TCP connection REQ 1 RESP 1 REQ 2 RESP 2 ⚠ HOL: REQ 3 waits for RESP 1 1 TCP connection Stream 1: REQ 1 ──── RESP 1 Stream 3: REQ 2 ──── RESP 2 Stream 5: REQ 3 ──── RESP 3 ✓ Parallel, no HTTP-layer HOL
Conditional Requests

HTTP/1.1 giới thiệu If-Modified-SinceIf-None-Match để validation cache, giúp server trả 304 Not Modified thay vì gửi lại toàn bộ body.

04

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).

MethodSafeIdempotentRequest BodyMô tả
GETKhôngLấy tài nguyên
HEADKhôngNhư GET nhưng không có body response
OPTIONSKhôngHỏi về capabilities của server/resource (CORS preflight)
POSTTạo resource mới hoặc trigger action
PUTThay thế toàn bộ resource
PATCH✗*Cập nhật một phần resource
DELETEThường khôngXóa resource
CONNECTKhôngTạo tunnel TCP (dùng cho HTTPS qua proxy)
TRACEKhôngEcho request (debugging, thường bị disable vì XST attack)
Safe vs Idempotent

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
05

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).

HTTP Request GET /api/users?page=1 HTTP/1.1 Host: api.example.com Accept: application/json Authorization: Bearer eyJhbGc... User-Agent: MyApp/2.0 (blank line CRLF) Body (POST/PUT/PATCH có body) start-line headers HTTP Response HTTP/1.1 200 OK Content-Type: application/json Content-Length: 342 Cache-Control: max-age=3600 ETag: "abc123" (blank line CRLF) [{"id":1,"name":"Alice"},...]

Request Headers phổ biến

HeaderVí dụMô tả
Hostexample.com:8080Bắt buộc trong HTTP/1.1 — tên domain + port
Acceptapplication/json, text/html;q=0.9Media types client chấp nhận
Accept-Encodinggzip, br, zstdCompression algorithms client hiểu
AuthorizationBearer <token>Credentials để authenticate
Cookiesession=abc; theme=darkCookies gửi lên server
Content-Typeapplication/json; charset=utf-8Media type của request body
If-None-Match"abc123"Conditional — trả 304 nếu ETag match
Originhttps://app.example.comOrigin của request (CORS)

Response Headers phổ biến

HeaderVí dụMô tả
Content-Typeapplication/json; charset=utf-8Media type của response body
Content-EncodinggzipCompression đã áp dụng
Cache-Controlmax-age=86400, publicCaching directives
ETag"33a64df5"Version identifier của resource
Locationhttps://example.com/newRedirect target (3xx) hoặc URL của resource mới tạo (201)
Set-Cookiesession=xyz; HttpOnly; SecureSet cookie trên client
Strict-Transport-Securitymax-age=31536000; includeSubDomainsForce HTTPS (HSTS)
Access-Control-Allow-Originhttps://app.example.comCORS — origin được phép
06

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

CodeTênMô tả
100ContinueServer đã nhận headers, client tiếp tục gửi body
101Switching ProtocolsServer chấp nhận upgrade (HTTP → WebSocket)

2xx — Success

CodeTênMô tả
200OKRequest thành công, response có body
201CreatedResource được tạo, trả về Location header
202AcceptedRequest được nhận, xử lý async
204No ContentThành công, không có body (DELETE, PUT thường dùng)
206Partial ContentRange request — chỉ trả một phần resource

3xx — Redirection

CodeTênPermanent?Method preserved?
301Moved Permanently✗ (POST → GET)
302Found✗ (POST → GET)
303See OtherLuôn GET
304Not Modified— (cache hit)
307Temporary Redirect✓ (POST stays POST)
308Permanent Redirect✓ (POST stays POST)

4xx — Client Errors

CodeTênMô tả
400Bad RequestRequest malformed, syntax sai
401UnauthorizedChưa authenticate — gửi credentials
403ForbiddenĐã authenticate nhưng không có quyền
404Not FoundResource không tồn tại
405Method Not AllowedMethod không được phép cho resource này
409ConflictState conflict (ví dụ: tạo duplicate, optimistic locking)
422Unprocessable EntitySyntax đúng nhưng semantics sai (validation errors)
429Too Many RequestsRate limit exceeded — thường có Retry-After header

5xx — Server Errors

CodeTênMô tả
500Internal Server ErrorLỗi không xác định phía server
502Bad GatewayProxy nhận response không hợp lệ từ upstream
503Service UnavailableServer quá tải hoặc đang maintenance
504Gateway TimeoutUpstream không phản hồi kịp thời
401 vs 403

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.

07

URL & Content Negotiation

Cấu trúc URL

URL (Uniform Resource Locator) theo RFC 3986 có cấu trúc phân cấp:

https://user:pass@api.example.com:8080/v2/users/42?sort=name&page=2#profile

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.

Vary Header

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.

08

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

DirectiveRequest / ResponseTác dụng
max-age=NCả haiResource có thể được cache N giây
s-maxage=NResponseNhư max-age nhưng chỉ cho shared cache (CDN)
no-cacheCả haiPhải revalidate với server trước khi dùng cache
no-storeCả haiKhông được lưu vào cache (sensitive data)
must-revalidateResponsePhải revalidate khi stale — không dùng stale response
stale-while-revalidate=NResponseServe stale trong N giây trong khi fetch mới ở background
stale-if-error=NResponseDùng stale nếu server lỗi, trong N giây
immutableResponseResource không bao giờ thay đổi — skip revalidation
privateResponseChỉ browser cache, không lưu vào shared cache
publicResponseCó 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 vs no-store

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.

09

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

AttributeTác dụngSecurity implication
HttpOnlyJavaScript không đọc được cookie (document.cookie)Ngăn XSS đánh cắp session cookie
SecureChỉ gửi qua HTTPSNgăn sniffing trên HTTP
SameSite=StrictKhông gửi trong cross-site requestsBảo vệ tốt nhất chống CSRF
SameSite=LaxGửi trong same-site + top-level navigation GETMặc định Chrome, cân bằng security/usability
SameSite=NoneGửi trong mọi cross-site requestPhải đi kèm Secure — dùng cho third-party cookies
Domain=.example.comChia sẻ cookie cho subdomainsMở rộng attack surface
Path=/apiChỉ gửi cho requests đến /api/*Giới hạn phạm vi
Max-Age=NSống N giây rồi expireKhông có → session cookie (xóa khi đóng browser)
Session Patterns

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.

10

CORS

Same-Origin Policy (SOP) — trình duyệt chặn JavaScript đọc response từ origin khác. Origin = scheme + host + port. https://app.comhttps://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 HeaderDirectionÝ nghĩa
Access-Control-Allow-OriginResponseOrigin được phép (hoặc *)
Access-Control-Allow-MethodsResponseMethods được phép
Access-Control-Allow-HeadersResponseRequest headers được phép
Access-Control-Allow-CredentialsResponsetrue nếu cho phép cookies/auth
Access-Control-Expose-HeadersResponseResponse headers JS được đọc
Access-Control-Max-AgeResponseCache preflight N giây
Pitfall phổ biến

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.

11

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.

SNI — Server Name Indication

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.

Certificate Transparency (CT)

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.

12

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.

Client Server TLS 1.3 — 1-RTT Handshake ClientHello supported cipher suites, key_share (ECDHE pub key), SNI, session ticket ServerHello selected cipher + key_share (server ECDHE pub key) → both derive session keys {EncryptedExtensions + Certificate + CertificateVerify} server cert + ECDSA/RSA signature over handshake transcript {Finished} HMAC over handshake transcript — server done {Finished} client Finished — handshake complete, keys verified ✓ Application Data (AEAD encrypted) GET /api/data HTTP/2 (encrypted) HTTP/2 200 OK + body (encrypted) 0-RTT Resumption (Session Ticket) ClientHello + early_data (PSK from prev session) — ⚠ replay attack risk Response (may accept early_data) 1 RTT

TLS 1.2 vs TLS 1.3

Khía cạnhTLS 1.2TLS 1.3
Handshake RTT2 RTT1 RTT (0-RTT với resumption)
Key exchangeRSA 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 encryptionPlaintext trong handshakeEncrypted sau ServerHello
RenegotiationCó (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
0-RTT Risks

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.

13

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.

Byte 0–2 Byte 3 Byte 4 Byte 5–8 Length (24 bits) — payload size, max 16,777,214 bytes (default max 16,384) Type (8 bits) Flags (8 bits) R Stream Identifier (31 bits) — 0 = connection-level frame Payload (variable — content depends on frame type) bit 0 bit 15 bit 31

Frame Types

TypeHexMô tả
DATA0x0Payload của request/response body
HEADERS0x1Mở stream + gửi header fields (HPACK-encoded)
PRIORITY0x2Stream priority (deprecated RFC 9113)
RST_STREAM0x3Cancel stream ngay lập tức
SETTINGS0x4Connection parameters (window size, max streams, ...)
PUSH_PROMISE0x5Server push announcement
PING0x6Keepalive + RTT measurement
GOAWAY0x7Graceful shutdown với last stream ID
WINDOW_UPDATE0x8Flow control — tăng window size
CONTINUATION0x9Header 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
14

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 vs GOAWAY

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
15

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.

Header Field e.g. :method: GET Static Table 61 entries (RFC-defined) idx 2 = :method GET idx 4 = :path / idx 31 = content-type Dynamic Table FIFO, per-connection idx 62+ (new headers) evicted by size limit default max: 4096 bytes miss Indexed (1 byte) ✓ Literal + index Never Index Literal no index hit Authorization, Cookie → Never Index (sensitive!)

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.

16

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).

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.

17

Security Headers

Ngoài TLS, HTTP cung cấp nhiều response headers để hardening bảo mật browser-side.

HeaderVí dụ giá trịBảo vệ chống
Strict-Transport-Securitymax-age=31536000; includeSubDomains; preloadSSL stripping, HTTP downgrade
Content-Security-Policydefault-src 'self'; script-src 'nonce-xxx'XSS, data injection, clickjacking
X-Frame-OptionsDENY hoặc SAMEORIGINClickjacking (legacy, dùng CSP frame-ancestors)
X-Content-Type-OptionsnosniffMIME-type sniffing attacks
Referrer-Policystrict-origin-when-cross-originRò rỉ URL trong Referer header
Permissions-Policycamera=(), microphone=(), geolocation=(self)Lạm dụng browser APIs
Cross-Origin-Opener-Policysame-originCross-origin window attacks (Spectre)
Cross-Origin-Embedder-Policyrequire-corpSharedArrayBuffer leaks (Spectre)
Cross-Origin-Resource-Policysame-originCross-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
CSP Gotchas
  • unsafe-inline trong 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ùng report-to với Reporting API
18

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.

HTTP/2 over TLS/TCP HTTP/2 Application TLS 1.3 TCP (stream-oriented, HOL blocking) IP New conn: TCP 3-way + TLS 1-RTT = 2 RTT HTTP/3 over QUIC/UDP HTTP/3 Application QUIC TLS 1.3 integrated · independent streams no TCP HOL · connection migration (CID) built-in congestion control (CUBIC/BBR) UDP + IP New conn: 1-RTT · Resumption: 0-RTT evolution

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ăngHTTP/1.1HTTP/2HTTP/3
TransportTCPTCPQUIC (UDP)
HandshakeTCP + TLS = 2 RTTTCP + TLS = 2 RTTQUIC = 1 RTT (0-RTT resume)
MultiplexingPipelining (HOL)Streams (TCP HOL)Streams (no HOL)
Header compressionKhôngHPACKQPACK
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
Câu hỏi hay gặp trong interviews
  • 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ì