CHƯƠNG 05 · APPLICATION · ~140 phút

HTTP/1.1, HTTP/2,
HTTP/3 — giao thức của Web

HTTP là giao thức quan trọng nhất với backend dev. Đa số phỏng vấn đều hỏi sâu: method, status code, header, idempotency, multiplexing, caching. Học chương này, bạn nắm: anatomy request/response, lý do HTTP/2 nhanh hơn, cách dùng ETag để giảm bandwidth.

5.1 HTTP Request/Response Anatomy

Request

GET /api/users/42 HTTP/1.1                    ← Request line: method path version
Host: api.example.com                          ← Headers
Accept: application/json
Authorization: Bearer eyJhbGc...
User-Agent: curl/7.64.1
Cookie: session=abc123

(empty line)
                                               ← (Body — GET thường không có)

Response

HTTP/1.1 200 OK                                ← Status line: version code reason
Content-Type: application/json                  ← Headers
Content-Length: 87
Cache-Control: max-age=3600
Server: nginx/1.21
Date: Sat, 09 May 2026 10:00:00 GMT

{"id": 42, "name": "Alice", "email": "..."}    ← Body

3 phần

  1. Start line: request line / status line
  2. Headers: key-value pairs, ngăn cách bởi :, kết thúc bằng dòng trống
  3. Body: data (tuỳ chọn)

Toàn bộ là plain text ASCII trong HTTP/1.1 — bạn có thể telnet đến port 80 và gõ tay request.

5.2 HTTP Methods

MethodMục đíchBodySafeIdempotentCacheable
GETĐọc resourceKhông
HEADNhư GET nhưng chỉ headersKhông
POSTTạo mới / submitHiếm
PUTReplace toàn bộ resource
PATCHUpdate một phần~
DELETEXoá resourceTuỳ
OPTIONSHỏi server method nào support (CORS preflight)Không
CONNECTTunnel (HTTPS proxy)
TRACEEcho request (debug)Không

Phân biệt POST vs PUT vs PATCH

  • POST /users: tạo user mới — server tự sinh ID. Không idempotent (gọi 2 lần → 2 user).
  • PUT /users/42: replace toàn bộ user 42 với data trong body. Idempotent (gọi nhiều lần kết quả giống nhau).
  • PATCH /users/42: update 1 vài field của user 42. Theo lý thuyết không idempotent, nhưng nếu client gửi field cụ thể (vd email=x) thì tương đương idempotent.

5.3 HTTP Status Codes — phải thuộc

1xx — Informational

  • 100 Continue — server bảo client gửi tiếp body
  • 101 Switching Protocols — vd upgrade lên WebSocket

2xx — Success

  • 200 OK — thành công, có body
  • 201 Created — POST thành công, resource được tạo
  • 202 Accepted — đã nhận request, xử lý async
  • 204 No Content — thành công, không có body (vd DELETE)
  • 206 Partial Content — response của Range request

3xx — Redirection

  • 301 Moved Permanently — vĩnh viễn, browser cache
  • 302 Found — tạm thời (đôi khi gọi 302 Moved Temporarily)
  • 304 Not Modified — client có cache hợp lệ, không cần download lại
  • 307 Temporary Redirect — như 302 nhưng giữ method (POST vẫn là POST)
  • 308 Permanent Redirect — như 301 nhưng giữ method

4xx — Client Error

  • 400 Bad Request — request sai cú pháp / data không hợp lệ
  • 401 Unauthorized — chưa auth (cần login)
  • 403 Forbidden — đã auth nhưng không có quyền
  • 404 Not Found — resource không tồn tại
  • 405 Method Not Allowed — method không support cho resource này
  • 409 Conflict — vd update với version cũ (optimistic lock)
  • 410 Gone — như 404 nhưng "đã từng tồn tại, đã xoá"
  • 413 Payload Too Large — body quá lớn
  • 422 Unprocessable Entity — syntax OK nhưng semantic sai (validation)
  • 429 Too Many Requests — rate limit

5xx — Server Error

  • 500 Internal Server Error — unhandled exception phía server
  • 501 Not Implemented — server không support method/feature
  • 502 Bad Gateway — proxy nhận response invalid từ upstream
  • 503 Service Unavailable — server quá tải / maintenance
  • 504 Gateway Timeout — proxy timeout chờ upstream
⚠️ Bẫy phỏng vấn: 401 vs 403
  • 401 Unauthorized: thực ra nghĩa là "Unauthenticated" — chưa login
  • 403 Forbidden: đã login nhưng không có permission
Tên gọi 401 sai về mặt từ ngữ, nhưng RFC định nghĩa thế.
⚠️ 301 vs 302 — SEO matters
  • 301 Permanent: search engine cập nhật URL mới, page rank chuyển sang URL mới
  • 302 Temporary: search engine không cập nhật, vẫn giữ URL cũ
Sai 302 thay 301 → mất SEO.

5.4 Headers Quan Trọng

Request Headers

  • Host: tên domain (bắt buộc HTTP/1.1) — cho phép virtual hosting (nhiều site trên 1 IP)
  • User-Agent: định danh client (browser, curl, app...)
  • Accept: client chấp nhận content type nào (vd application/json)
  • Accept-Encoding: client decode được gì (gzip, br)
  • Accept-Language: ngôn ngữ ưu tiên
  • Authorization: credentials (Bearer token, Basic auth)
  • Cookie: gửi cookie client đang lưu
  • Content-Type: type của body (POST/PUT)
  • Content-Length: kích thước body
  • Referer (sic): URL trang trước
  • Origin: origin của request (CORS)
  • If-None-Match: ETag client đang có (cho 304)

Response Headers

  • Content-Type: type body trả về
  • Content-Length: kích thước body
  • Content-Encoding: nén gì (gzip, br)
  • Cache-Control: cache strategy (max-age, no-cache, no-store, public, private)
  • ETag: identifier version của resource
  • Last-Modified: thời gian update cuối
  • Set-Cookie: bảo browser lưu cookie
  • Location: URL redirect (3xx)
  • Access-Control-Allow-Origin: CORS
  • Strict-Transport-Security (HSTS): bắt browser luôn HTTPS
  • Content-Security-Policy (CSP): chống XSS

5.5 HTTP/1.1 (1997) — text-based, vẫn phổ biến

Đặc điểm

  • Plain text — đọc được bằng telnet
  • Mỗi request/response 1 cặp — synchronous trên 1 connection
  • Persistent connection (keep-alive default) — tái sử dụng TCP cho nhiều request
  • Pipelining (lý thuyết): gửi nhiều request không đợi response — nhưng response vẫn phải theo thứ tự (HOL block) → ít browser dùng

Vấn đề HTTP/1.1

  • Head-of-line blocking ở app layer: 1 connection chỉ xử lý 1 request tại 1 thời điểm
  • Browser mở 6 TCP connection song song để workaround → tốn server resource
  • Header lặp lại mỗi request → overhead
  • Text format → parse chậm

Demo telnet

telnet example.com 80
Trying 93.184.216.34...
Connected to example.com.

GET / HTTP/1.1
Host: example.com
[gõ Enter 2 lần]

HTTP/1.1 200 OK
Content-Type: text/html
...

5.6 HTTP/2 (2015) — binary, multiplexed

Kế thừa Google SPDY. Giải quyết các vấn đề HTTP/1.1.

4 đổi mới chính

1. Binary framing thay text

Thay vì plaintext, HTTP/2 dùng binary frame — parse nhanh hơn, ít error hơn.

2. Multiplexing — nhiều stream trên 1 TCP connection

Cùng 1 TCP, nhiều request "đan xen" qua các stream. Không cần mở nhiều TCP. Không có HOL ở app layer (nhưng vẫn có HOL ở TCP — sẽ giải quyết ở HTTP/3).

HTTP/1.1: 6 TCP connections, mỗi cái 1 request tại 1 lúc ┌─Conn1─┐ ┌─Conn2─┐ ... ┌─Conn6─┐ HTTP/2: 1 TCP connection, nhiều stream song song ┌─────────── 1 TCP ───────────┐ │ Stream 1: req A → res A │ │ Stream 3: req B → res B │ ← interleaved frames │ Stream 5: req C → res C │ └─────────────────────────────┘

3. Header compression — HPACK

Nhiều request có headers giống nhau (cookie, user-agent...). HPACK dùng dictionary + Huffman coding nén headers, giảm rất nhiều bandwidth.

4. Server Push (ít dùng, đã deprecate ở 1 số browser)

Server có thể "đẩy" resource liên quan trước khi client request. Vd: gửi style.css luôn khi client request index.html.

Thực tế ít hiệu quả → Chrome đã bỏ support 2022. Thay bằng 103 Early Hints.

Vẫn còn vấn đề: TCP HOL blocking

Nhiều stream trên 1 TCP — nếu 1 packet TCP mất, tất cả stream đều bị block đợi retransmit (đã giải thích ở Chương 4).

5.7 HTTP/3 (2022) — chạy trên QUIC

Giải quyết TCP HOL blocking bằng cách... bỏ TCP! Dùng QUIC trên UDP.

Lợi ích so với HTTP/2

  • Per-stream HOL: 1 stream mất packet không block stream khác
  • 0-RTT connection với resumption (HTTP/2 + TLS = 3 RTT setup)
  • Connection migration: đổi mạng (Wi-Fi → 4G) không phải reconnect
  • Built-in TLS 1.3: HTTPS bắt buộc

Adoption

Cloudflare, Google, Facebook đã enable HTTP/3 từ 2020+. Chrome, Firefox, Safari, curl 7.66+ đều support.

curl --http3 https://www.cloudflare.com -I
# HTTP/3 200
# server: cloudflare
# ...

So sánh 3 phiên bản

Tính chấtHTTP/1.1HTTP/2HTTP/3
Năm199720152022
FormatTextBinaryBinary
TransportTCPTCPQUIC (UDP)
MultiplexKhông (cần nhiều TCP)
HOL blockingApp levelTCP levelKhông
Header compressionKhôngHPACKQPACK
Setup latency1 RTT TCP + 2 RTT TLS = 3 RTT1 + 2 = 3 RTT0-1 RTT

5.8 Idempotency & Safety — phải hiểu đúng

Định nghĩa

  • Safe = không thay đổi state server. GET, HEAD, OPTIONS.
  • Idempotent = gọi nhiều lần kết quả giống gọi 1 lần. GET, PUT, DELETE, HEAD.
  • POST = không idempotent (mỗi lần POST tạo 1 row mới)
  • PATCH = thường idempotent nếu là "set value" thay vì "increment"

Tại sao quan trọng?

Network không tin cậy. Request có thể fail giữa chừng — client không biết server đã xử lý chưa. Retry là pattern phổ biến.

Retry idempotent operation an toàn (gọi 2 lần = 1 lần). Retry non-idempotent (POST) có thể tạo duplicate.

Solution: Idempotency Key

POST /api/payment HTTP/1.1
Idempotency-Key: 8e7c4f2a-a8c1-4e58-9b7c-...
Content-Type: application/json

{"amount": 100, "currency": "USD"}

Server lưu key + result. Nếu request lại với cùng key, trả result cũ → không tạo payment thứ 2. Stripe, PayPal đều dùng pattern này.

5.9 HTTP Caching — giảm bandwidth, tăng tốc

Cache-Control header

Cache-Control: public, max-age=3600, immutable
Cache-Control: no-cache       # phải revalidate mỗi lần
Cache-Control: no-store       # không được cache (sensitive data)
Cache-Control: private        # chỉ cache trên browser, không proxy

ETag — version identifier

Server gửi ETag cùng response. Lần sau client gửi If-None-Match: <etag>. Nếu resource không đổi → server trả 304 Not Modified không có body → tiết kiệm bandwidth.

# Lần đầu
GET /api/users/42
→ 200 OK
  ETag: "abc123"
  {"id": 42, "name": "Alice"}

# Lần sau
GET /api/users/42
If-None-Match: "abc123"
→ 304 Not Modified
  (không có body)

Last-Modified — cũ hơn ETag

GET /api/users/42
If-Modified-Since: Sat, 09 May 2026 10:00:00 GMT
→ 304 Not Modified hoặc 200 OK

Cache hierarchy

  1. Browser memory cache (mới nhất, nhanh nhất)
  2. Browser disk cache
  3. Service worker cache
  4. CDN edge cache
  5. Reverse proxy cache (nginx, Varnish)
  6. Origin server

5.10 Compression — giảm kích thước

HTTP body có thể nén để giảm bandwidth.

Request:
  Accept-Encoding: gzip, deflate, br

Response:
  Content-Encoding: gzip
  (body đã nén)

Algorithms

  • gzip: phổ biến nhất, ~50-70% giảm cho text
  • deflate: ít dùng (lý do lịch sử)
  • brotli (br): hơn gzip 15-20% cho text, do Google. Hỗ trợ tốt trên modern browser
  • zstd: mới hơn, đang được adopt

Khi nào KHÔNG nén?

  • Image, video — đã nén sẵn
  • Sensitive data (vd JWT trong body) — có thể leak qua side channel (BREACH attack)
  • Body nhỏ < ~1KB — overhead lớn hơn lợi ích

Bài tập

Bài 1 — Telnet HTTP/1.1

Mở terminal, gõ telnet example.com 80. Gõ GET / HTTP/1.1, Enter, Host: example.com, Enter 2 lần. Quan sát response.

Bài 2 — Status code matching

Mỗi case sau, server nên trả status nào? (a) Login sai password; (b) Submit form với email bị trùng; (c) Endpoint POST đến URL chỉ chấp nhận GET; (d) DB bị down; (e) Image quá lớn.

Bài 3 — POST vs PUT vs PATCH

Cho REST API quản lý sản phẩm: viết URL + method cho từng case: (a) Tạo sản phẩm mới; (b) Update toàn bộ thông tin sản phẩm 5; (c) Đổi giá sản phẩm 5; (d) Xoá sản phẩm 5.

Bài 4 — Quan sát HTTP/2 vs /1.1

Mở Chrome DevTools → Network → enable cột "Protocol". Browse google.com vs 1 trang nhỏ tự host. So sánh: protocol nào, số connection.

Bài 5 — ETag thực hành

Viết Express endpoint trả JSON với header ETag. Test: lần 1 nhận 200; lần 2 với If-None-Match nhận 304.

Bài 6 — Idempotency Key

Thiết kế API POST /payments support Idempotency-Key. Pseudocode lưu key trong Redis với TTL 24h.

Bài 7 — HTTP/3 detection

Chạy curl --http3 https://cloudflare.com -I. Có ra HTTP/3 không? Nếu chưa, chrome://net-export hoặc Firefox protocol indicator.

🧪 Quiz cuối chương

Câu 1. Phân biệt 401 và 403?

  • 401 = server lỗi; 403 = client lỗi
  • 401 = chưa auth (chưa login); 403 = đã auth nhưng không có quyền
  • 401 = HTTP, 403 = HTTPS
  • Hai cái giống nhau

Đáp án: chưa auth vs không có quyền. Tên 401 "Unauthorized" gây hiểu nhầm — thực ra là "Unauthenticated".

Câu 2. 301 vs 302 khác nhau ở đâu?

  • 301 vĩnh viễn (search engine update URL); 302 tạm thời
  • Hai cái giống nhau
  • 301 = redirect, 302 = forward
  • 301 chỉ cho HTTP, 302 cho HTTPS

Đáp án: vĩnh viễn vs tạm thời. Quan trọng cho SEO. Sai 302 thay 301 → mất page rank.

Câu 3. Method nào idempotent?

  • POST
  • POST và PATCH
  • GET, PUT, DELETE, HEAD
  • Chỉ GET

Đáp án: GET, PUT, DELETE, HEAD. POST tạo mới mỗi lần → không idempotent. PATCH thường nhưng không bắt buộc.

Câu 4. HTTP/2 nhanh hơn HTTP/1.1 ở đâu?

  • Encryption nhanh hơn
  • Multiplexing — nhiều request song song trên 1 TCP; binary framing; HPACK header compression
  • Server xử lý nhanh hơn
  • Hai cái cùng tốc độ

Đáp án: multiplexing + binary + HPACK. HTTP/1.1 1 connection 1 request → cần mở 6 TCP. HTTP/2 1 TCP nhiều stream.

Câu 5. HTTP/3 chạy trên?

  • QUIC (UDP)
  • TCP
  • WebSocket
  • SCTP

Đáp án: QUIC. Tránh TCP head-of-line blocking. 0-RTT, connection migration.

Câu 6. ETag để làm gì?

  • Authentication
  • Compression
  • Cache validation — client gửi ETag, server check; nếu không đổi trả 304 (no body) tiết kiệm bandwidth
  • Routing

Đáp án: cache validation. Client gửi If-None-Match: <etag>; server trả 304 nếu khớp.

Câu 7. Tại sao GET nên idempotent & safe?

  • Vì spec yêu cầu
  • Để browser/proxy cache an toàn, retry an toàn — search engine crawl không gây side effect
  • Để bảo mật
  • Để chạy nhanh hơn

Đáp án: cache + retry + crawl an toàn. Nếu GET tạo state → search engine crawl link sẽ gây vô số side effect.

Câu 8. Khi nào dùng PUT vs POST?

  • POST tạo mới (server cấp ID); PUT replace toàn bộ resource đã biết ID
  • POST cho text, PUT cho file
  • Hai cái giống nhau
  • POST không có body, PUT có

Đáp án: POST tạo mới, PUT replace. POST /users server cấp ID; PUT /users/42 client biết ID, replace toàn bộ.

Tổng kết chương 5

  • ✅ HTTP request/response: start line + headers + body
  • ✅ Methods: GET (read), POST (create), PUT (replace), PATCH (update partial), DELETE
  • ✅ Status codes: 2xx success, 3xx redirect, 4xx client error, 5xx server error
  • ✅ Bẫy 401 (chưa auth) vs 403 (không quyền); 301 (perm) vs 302 (temp)
  • HTTP/1.1: text, persistent connection, head-of-line ở app
  • HTTP/2: binary, multiplexing, HPACK — vẫn TCP HOL
  • HTTP/3: trên QUIC/UDP, per-stream HOL, 0-RTT, connection migration
  • Idempotency Key: pattern an toàn cho retry POST
  • ✅ Cache: Cache-Control, ETag + If-None-Match → 304
  • ✅ Compression: gzip, brotli — không nén media/sensitive data
← Chương trước Chương 04: UDP Chương kế tiếp Chương 06: HTTPS, TLS →