Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

HTTP Request và Response: cấu trúc đầy đủ

API and Technical Fundamentals cho BA Bài 5/60

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là một BA đang ngồi họp với team kỹ thuật để bàn về tích hợp cổng thanh toán cho một ứng dụng đặt vé xe khách. Dev frontend nói: "Mình gửi request lên server mà nó trả về 400, body thì rỗng". Dev backend đáp lại: "Lạ nhỉ, header Content-Type của bạn có đúng không?". Nếu bạn không hiểu họ đang nói gì, bạn chỉ biết ngồi gật đầu và ghi chép một cách máy móc. Nhưng nếu bạn nắm vững cấu trúc của một HTTP request và response, bạn sẽ hiểu ngay vấn đề nằm ở đâu, thậm chí có thể đặt câu hỏi đúng trọng tâm để tháo gỡ.

Ở bài trước, bạn đã làm quen với REST API ở mức tổng quan và biết JSON là gì. Bài này, chúng ta sẽ "mổ xẻ" chi tiết một cuộc trao đổi HTTP gồm hai phần: thông điệp client gửi đi (request) và thông điệp server gửi về (response). Đây là nền tảng quan trọng bậc nhất — bởi vì gần như mọi API mà bạn gặp trong sự nghiệp BA đều "chạy" trên HTTP. Hiểu rõ cấu trúc đầy đủ của request và response giúp bạn đọc được tài liệu API, viết được spec rõ ràng, debug cơ bản, và giao tiếp với dev bằng đúng ngôn ngữ của họ.

Lưu ý: Bài này tập trung vào bức tranh tổng thể cấu trúc của một HTTP message. Những phần chuyên sâu như từng HTTP method, từng status code, hay từng header cụ thể sẽ được đào sâu ở các bài sau. Ở đây, mục tiêu là bạn nhìn được "bộ khung xương" hoàn chỉnh của cả request lẫn response.

Khái niệm cốt lõi

HTTP là gì?

HTTP (HyperText Transfer Protocol — giao thức truyền tải siêu văn bản) là một bộ quy tắc để client (trình duyệt web, ứng dụng di động, hoặc một server khác) "nói chuyện" với server thông qua mạng. HTTP hoạt động trên nền TCP/IP — tức là tầng vận chuyển đảm bảo dữ liệu đến nơi đầy đủ, còn HTTP định nghĩa hình dạng của thông điệp được trao đổi.

Có hai đặc điểm cốt lõi của HTTP mà một BA cần ghi nhớ:

  • Mô hình request–response: Client luôn là bên chủ động gửi yêu cầu (request), server là bên phản hồi (response). Server không tự nhiên "gọi điện" cho client trước (muốn server chủ động đẩy dữ liệu, người ta dùng cơ chế khác như Webhook hay WebSocket — sẽ học sau).
  • Stateless (không trạng thái): Mỗi request là độc lập. Server không "nhớ" request trước đó của bạn. Nếu cần xác thực, mỗi request phải tự mang theo thông tin nhận diện (ví dụ token trong header). Điều này giải thích vì sao mọi lần gọi API bạn đều phải gửi kèm Authorization.

Cấu trúc một HTTP Request

Một request gồm bốn thành phần, xếp theo thứ tự từ trên xuống:

1. Request Line (dòng yêu cầu) — dòng đầu tiên, gồm ba phần:

  • Method: hành động muốn thực hiện (GET để lấy, POST để tạo, PUT/PATCH để sửa, DELETE để xóa...).
  • Path / URL: địa chỉ tài nguyên muốn tác động, ví dụ /api/v1/orders/123.
  • Phiên bản HTTP: ví dụ HTTP/1.1.
Ví dụ: GET /api/v1/products?category=skincare HTTP/1.1

2. Headers (phần đầu) — các cặp Key: Value mô tả metadata của request. Ví dụ:

  • Host: api.vietnamcos.com — server đích.
  • Authorization: Bearer eyJhbGc... — thông tin xác thực.
  • Content-Type: application/json — định dạng của body.
  • Accept: application/json — định dạng client mong muốn nhận về.
3. Dòng trống — một dòng trống ngăn cách giữa headers và body. Nhỏ nhưng bắt buộc về mặt kỹ thuật.

4. Body (phần thân) — dữ liệu gửi kèm, thường có với POST/PUT/PATCH. Với GET thì thường không có body. Body có thể là JSON, form data, hoặc file.

Một request POST hoàn chỉnh trông như sau:

POST /api/v1/orders HTTP/1.1
Host: api.vietnamcos.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR...
Content-Type: application/json
Accept: application/json

{ "product_id": 789, "quantity": 2, "shipping_city": "Da Nang" }

Cấu trúc một HTTP Response

Response cũng có bốn phần tương tự, chỉ khác dòng đầu tiên:

1. Status Line (dòng trạng thái) — gồm phiên bản HTTP, mã trạng thái (status code), và mô tả ngắn. Ví dụ: HTTP/1.1 201 Created.

2. Headers — metadata của response, ví dụ:

  • Content-Type: application/json — định dạng body server trả về.
  • Content-Length: 142 — độ dài body tính theo byte.
  • Cache-Control: no-store — chỉ dẫn về cache.
  • X-RateLimit-Remaining: 98 — số request còn lại trước khi bị giới hạn.
3. Dòng trống.

4. Body — nội dung server trả về, thường là JSON với dữ liệu hoặc thông báo lỗi.

Một response hoàn chỉnh:

HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 124
Location: /api/v1/orders/456

{ "order_id": 456, "status": "confirmed", "total": 540000, "currency": "VND" }

Status code — nhóm "tín hiệu giao thông" của response

Mã trạng thái là ba chữ số, chia thành năm nhóm. Bạn chỉ cần nhớ ý nghĩa của chữ số đầu tiên:

  • 1xx — thông tin (hiếm gặp trong công việc BA hằng ngày).
  • 2xx — thành công (200 OK, 201 Created, 204 No Content).
  • 3xx — chuyển hướng (301, 302).
  • 4xx — lỗi từ phía client, tức bên gọi sai (400 Bad Request, 401 Unauthorized, 404 Not Found).
  • 5xx — lỗi từ phía server, tức bên server hỏng (500 Internal Server Error, 503 Service Unavailable).
Mẹo ghi nhớ nhanh: 4xx là "lỗi tại bạn", 5xx là "lỗi tại tôi (server)". Phần chi tiết từng mã sẽ học ở bài chuyên sâu về status codes.

Tình huống thực tế

Tình huống 1: Tích hợp thanh toán cho ứng dụng đặt vé xe khách (Đà Nẵng)

Một startup ở Đà Nẵng làm app đặt vé xe khách tên "VéNhanh" tích hợp với cổng thanh toán nội địa. Khi khách bấm "Thanh toán", app gửi một request:

POST /v2/transactions HTTP/1.1
Host: sandbox.payment-gw.vn
Content-Type: application/json
Authorization: Bearer sk_test_8f2a...

{ "amount": 250000, "order_id": "VN-20260627-001", "method": "qr" }

Trong đợt test, team nhận về 400 Bad Request với body { "error": "amount must be in cents" }. Hóa ra cổng thanh toán yêu cầu số tiền tính theo đơn vị nhỏ nhất, tức 25000000 chứ không phải 250000.

Bài học rút ra: Status code 4xx báo lỗi từ phía client, và quan trọng hơn — body của response chứa thông tin chẩn đoán. Là BA viết spec tích hợp, bạn phải ghi rõ định dạng và đơn vị của từng field trong request body. Một dòng ghi chú "amount: số nguyên, đơn vị VND × 100" có thể tiết kiệm cả buổi debug.

Tình huống 2: BA đọc log để phân biệt lỗi của ai

Tại một sàn thương mại điện tử mỹ phẩm, bộ phận chăm sóc khách hàng báo: "Khách phàn nàn không đặt được hàng vào khung 20h tối". BA được giao điều tra. Mở log API, bạn thấy hàng loạt response 503 Service Unavailable với header Retry-After: 30 trong giờ cao điểm.

Nhờ hiểu rằng 5xx là lỗi phía server, BA kết luận ngay: đây không phải lỗi nhập liệu của khách, mà là server quá tải. BA viết báo cáo đề xuất team hạ tầng tăng năng lực xử lý vào giờ cao điểm — thay vì lãng phí thời gian đổ lỗi cho UX hay hướng dẫn người dùng.

Bài học rút ra: Chỉ cần đọc đúng status code và một vài header, BA đã định hướng được nguyên nhân và giao đúng việc cho đúng người. Phân biệt 4xx và 5xx là kỹ năng "đọc bệnh án" cơ bản.

Tình huống 3: Header bị bỏ sót khi tích hợp đối tác giao hàng

Một công ty logistics tích hợp API của một đối tác giao hàng để tạo đơn vận chuyển. Dev gửi đúng method, đúng path, body JSON đẹp đẽ, nhưng nhận về 415 Unsupported Media Type. Cả team bối rối vì "dữ liệu rõ ràng là JSON mà".

Nguyên nhân: họ quên đặt header Content-Type: application/json. Server không tự đoán định dạng body, nó đọc header để biết phải hiểu body theo kiểu gì. Thiếu header này, server từ chối xử lý.

Bài học rút ra: Headers không phải phần "trang trí" — chúng là chỉ dẫn bắt buộc để hai bên hiểu nhau. Khi review spec tích hợp, BA nên có một checklist header tối thiểu: Host, Authorization, Content-Type, Accept. Thiếu một cái là có thể hỏng cả luồng.

Hướng dẫn từng bước

Đây là quy trình để bạn tự "đọc" một cuộc trao đổi HTTP bất kỳ, rất hữu ích khi xem tài liệu API hoặc dùng công cụ như trình duyệt.

Bước 1 — Mở DevTools để quan sát request thật. Trên trình duyệt Chrome, nhấn F12, chọn tab Network, rồi tải lại một trang web hoặc thao tác trên một ứng dụng. Bạn sẽ thấy danh sách các request thật đang diễn ra.

Bước 2 — Đọc request line. Bấm vào một request, xem mục General: nó dùng method gì (GET/POST...), gọi đến URL nào. Đây là "ai làm gì với cái gì".

Bước 3 — Đọc request headers. Tìm Content-Type, Authorization, Accept. Tự hỏi: client đang gửi dữ liệu định dạng gì, có mang theo token xác thực không.

Bước 4 — Đọc request body (nếu có). Với POST/PUT, xem tab Payload hoặc Request. Đối chiếu từng field với tài liệu API: tên field, kiểu dữ liệu, có bắt buộc không.

Bước 5 — Đọc status line của response. Con số đầu tiên cho bạn biết ngay kết quả: 2xx là ổn, 4xx/5xx là có vấn đề.

Bước 6 — Đọc response headers và body. Xem Content-Type server trả về, và mở tab Response để xem dữ liệu hoặc thông báo lỗi. Đây là nơi chứa "câu trả lời" hoặc "lý do thất bại".

Bước 7 — Ghi lại thành tài liệu. Khi viết spec, hãy mô tả đầy đủ cả hai chiều: request mẫu (method, path, headers, body) và response mẫu cho cả trường hợp thành công lẫn thất bại. Một spec thiếu ví dụ response lỗi là một spec chưa hoàn chỉnh.

Lỗi thường gặp & mẹo

Lỗi 1 — Nhầm lẫn giữa "lỗi mạng" và "lỗi nghiệp vụ". Nhiều BA mới thấy có response trả về là tưởng "thành công". Thực ra một response 404 vẫn là một response hoàn chỉnh về mặt HTTP — kết nối thành công, chỉ là tài nguyên không tồn tại. Hãy luôn nhìn status code, đừng chỉ nhìn "có phản hồi hay không".

Lỗi 2 — Quên rằng body và header phải khớp nhau. Đặt Content-Type: application/json nhưng lại gửi body dạng form, hoặc ngược lại, là nguyên nhân kinh điển của lỗi 400/415. Mẹo: trong spec, luôn ghi cặp đôi "Content-Type này thì body phải có hình dạng kia".

Lỗi 3 — Bỏ qua response của trường hợp lỗi khi viết spec. Dev thường chỉ được cho ví dụ "happy path". Khi sản phẩm gặp lỗi thật, không ai biết server nên trả về gì. Mẹo: với mỗi endpoint, BA hãy yêu cầu mô tả ít nhất 2 response — một thành công (2xx) và một thất bại điển hình (4xx).

Lỗi 4 — Nghĩ rằng GET có thể mang body để truyền dữ liệu lớn. Theo thông lệ, GET truyền tham số qua query string trên URL, không qua body. Nếu cần gửi dữ liệu phức tạp, đó là dấu hiệu nên dùng POST. (Chi tiết về URL và method ở các bài sau.)

Mẹo vàng: Khi giao tiếp với dev về một sự cố API, hãy luôn hỏi đủ bốn thứ: method gì, gọi URL nào, status code trả về bao nhiêu, và body response nói gì. Bốn thông tin này gần như luôn đủ để khoanh vùng vấn đề mà không cần bạn phải biết code.

Bài tập thực hành

  • Đọc request thật: Mở Chrome DevTools (F12 → Network), truy cập một trang web bất kỳ. Chọn một request và ghi lại đầy đủ: method, URL, ba header quan trọng nhất, status code của response. Trình bày thành một bảng nhỏ.
  • Phân loại status code: Cho danh sách sau — 200, 201, 400, 401, 404, 500, 503. Hãy ghi mỗi mã thuộc nhóm "thành công / lỗi client / lỗi server" và viết một câu mô tả tình huống thực tế khi nó xuất hiện.
  • Viết spec mini: Giả sử bạn thiết kế endpoint tạo tài khoản người dùng cho một app Việt Nam. Hãy viết: một request mẫu (method, path, headers, body JSON với các field như họ tên, số điện thoại, email) và hai response mẫu — một thành công (201) và một thất bại khi số điện thoại đã tồn tại (chọn status code và body phù hợp).
  • Tìm lỗi header: Cho một request gửi body JSON nhưng có header Content-Type: text/plain. Hãy chỉ ra vấn đề, dự đoán status code server có thể trả về, và đề xuất cách sửa.

Tóm tắt

  • HTTP là giao thức request–response, stateless, chạy trên TCP/IP, là nền tảng của hầu hết mọi API mà BA gặp.
  • Một request gồm: request line (method + path + version), headers, dòng trống, và body.
  • Một response gồm: status line (version + status code + mô tả), headers, dòng trống, và body.
  • Headers là metadata bắt buộc giúp hai bên hiểu nhau; Content-Type, Authorization, Accept là những header cốt lõi cần ghi rõ trong spec.
  • Status code là tín hiệu nhanh nhất: 2xx thành công, 4xx lỗi phía client, 5xx lỗi phía server.
  • Là BA, kỹ năng quan trọng nhất là đọc được đầy đủ một cuộc trao đổi HTTP và mô tả lại nó trong tài liệu — gồm cả trường hợp thành công lẫn thất bại. Bốn câu hỏi "method gì, URL nào, status code mấy, body nói gì" sẽ là kim chỉ nam mỗi khi bạn cần debug hoặc trao đổi với dev.