กายวิภาคของข้อความ HTTP
การออกแบบ API ให้ดีเริ่มต้นจากการมองเห็นอย่างชัดเจนว่ามีอะไรวิ่งผ่านสายส่งบ้าง การแลกเปลี่ยน HTTP ก็เป็นเพียงข้อความเท่านั้น คือ request จาก client และ response จาก server ซึ่งแต่ละฝั่งมีสามส่วนเหมือนกัน
Request
หัวข้อที่มีชื่อว่า “Request”request มี start line (method + target + เวอร์ชัน HTTP) ชุดของ header และ body ที่จะมีหรือไม่ก็ได้:
POST /articles HTTP/1.1Host: api.example.comContent-Type: application/jsonAuthorization: Bearer eyJhbGci...Accept: application/json
{ "title": "Designing APIs", "body": "..." }method (POST) บอกว่า จะทำ อะไร target (/articles) บอกว่า ทำกับ อะไร ส่วน header พกพา metadata (content type, auth, สิ่งที่ client ยอมรับได้) และ body พกพา payload
Response
หัวข้อที่มีชื่อว่า “Response”response สะท้อนรูปแบบนั้น คือ status line (เวอร์ชัน + status code + reason) header และ body ที่จะมีหรือไม่ก็ได้:
HTTP/1.1 201 CreatedContent-Type: application/jsonLocation: /articles/42
{ "id": 42, "title": "Designing APIs" }flowchart LR
subgraph Request
A[Start line: method + path] --> B[Headers] --> C[Body optional]
end
subgraph Response
D[Status line: code + reason] --> E[Headers] --> F[Body optional]
end
Request -->|over HTTP| Response การสร้าง response ใน code
หัวข้อที่มีชื่อว่า “การสร้าง response ใน code”framework ฝั่ง server ซ่อนรายละเอียดเหล่านี้ไว้เกือบทั้งหมด แต่การได้ลองสร้าง response ด้วยมือสักครั้งก็ช่วยได้มาก โค้ดส่วนนี้สร้าง header และ JSON body สำหรับ response แบบ “created” แล้ว log ออกมา:
| ข้อดี (HTTP Structure) | ข้อแลกเปลี่ยน |
|---|---|
| มาตรฐานสากล — ทุก client รู้วิธีอ่าน request/response | verbose กว่า binary protocol เช่น gRPC |
| text-based — human-readable, ง่าย debug ด้วย curl | header overhead ทุก request — HTTP/2 แก้ด้วย header compression |
| stateless — ทุก request มีข้อมูลครบในตัวเอง | ต้องส่ง auth header ทุกครั้ง ต่างจาก session-based |
| cacheable — browser และ CDN cache ได้จาก header | caching config ผิดทำให้ client เห็นข้อมูลเก่า |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”ใส่ข้อมูลสำคัญใน URL แทน Header อาการ:
- ส่ง token ใน query string:
GET /users?token=abc123 - token ติด URL ทำให้ log และ browser history เก็บไว้
- ใช้
Authorization: Bearer <token>ใน header เสมอ
ไม่ Set Content-Type อาการ:
- ส่ง JSON body โดยไม่ใส่
Content-Type: application/json - server parse body ผิด หรือ reject request
- ตั้ง Content-Type ทุกครั้งที่ request มี body
💡 ตัวอย่างจากของจริง
GitHub API:
- ทุก request ต้องมี
Accept: application/vnd.github+json- บอก server ว่า client ต้องการ JSON response version ล่าสุด
Stripe API:
- ใช้
Idempotency-Keyheader สำหรับ POST request ที่ sensitive- ป้องกัน duplicate charge เมื่อ network retry