GET & POST
GET และ POST คือสอง method ที่คุณจะใช้บ่อยที่สุด ทั้งคู่อยู่คนละขั้วของสเปกตรัมเรื่อง safety โดย GET ทำได้แค่อ่าน ส่วน POST ใช้สร้างของใหม่ และเป็น method ที่มีข้อจำกัดน้อยที่สุดในบรรดาทั้งหมด
GET — safe และ cache ได้
หัวข้อที่มีชื่อว่า “GET — safe และ cache ได้”GET ดึง representation ของ resource มา และต้องไม่เปลี่ยน state ของ server เด็ดขาด เพราะเป็น safe method จึงนำ response ไป cache ได้ และ retry ได้อย่างอิสระ GET บน collection จะคืนรายการกลับมา ส่วน GET บน item เดียวจะคืน item นั้นหรือ 404
GET /articles/42 HTTP/1.1Accept: application/jsonGET ไม่ควรพก request body ที่มีความหมายติดไปด้วย และต้องไม่มี side effect — ห้ามทำอย่าง “เพิ่มยอดวิวผ่าน GET” ไม่เช่นนั้น cache และ prefetcher จะสร้างเรื่องเซอร์ไพรส์ให้คุณ
POST — การสร้างและการกระทำที่ไม่ idempotent
หัวข้อที่มีชื่อว่า “POST — การสร้างและการกระทำที่ไม่ idempotent”POST ส่งข้อมูลไปยัง collection ซึ่งโดยทั่วไปคือการสร้าง resource ใหม่ ไม่ safe และไม่ idempotent การส่ง POST เดิมซ้ำสองครั้งมักจะได้ resource ขึ้นมาสองตัว เมื่อสำเร็จ ให้คืน 201 Created พร้อม header Location ที่ชี้ไปยัง resource ใหม่
ทั้งสองอย่าง ใน API ที่กำลังทำงานจริง
หัวข้อที่มีชื่อว่า “ทั้งสองอย่าง ใน API ที่กำลังทำงานจริง”แอป Hono ตัวนี้เปิด collection ที่คุณอ่านและเพิ่มข้อมูลเข้าไปได้ ลองเปิดใน StackBlitz แล้วยิง GET /articles, GET /articles/1 และ POST /articles ดู:
| Method | Safe? | Idempotent? | เหมาะกับ |
|---|---|---|---|
| GET | ✅ | ✅ | อ่านข้อมูล, search, filter |
| POST | ❌ | ❌ | สร้าง resource, trigger action |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”ใช้ GET เพื่อ Trigger Side Effect อาการ:
GET /users/\{id\}/activate— activate user ผ่าน GET- bot, crawler, prefetch trigger action โดยไม่ตั้งใจ
- action ที่มี side effect ต้องใช้ POST, PUT, PATCH, หรือ DELETE
ส่ง Sensitive Data ใน GET Query String อาการ:
GET /login?password=secret123- password ติด URL, server log, browser history
- ใช้ POST พร้อม body สำหรับ sensitive data
💡 ตัวอย่างจากของจริง
GitHub API:
GET /repos/\{owner\}/\{repo\}— อ่านข้อมูล repo (safe, idempotent)POST /repos/\{owner\}/\{repo\}/issues— สร้าง issue ใหม่ (ไม่ idempotent)Stripe API:
GET /charges/\{id\}— ดู charge (cacheable)POST /charges— สร้าง charge ใหม่ (ต้องการ idempotency key)