ข้ามไปยังเนื้อหา

Content Negotiation

resource เดียวสามารถมีได้หลาย representation — JSON, CSV, ภาษาต่าง ๆ Content negotiation ให้ client ระบุความต้องการและให้ server เลือกตัวที่ตรงที่สุด ทั้งหมดนี้โดยไม่ต้องเปลี่ยน URI

client ส่ง Accept เพื่อบอกว่ารับ media type ไหนได้บ้าง และอาจส่ง Accept-Language มาด้วย จากนั้น server ตอบกลับด้วย representation ที่เลือกแล้ว พร้อม Content-Type ที่ตรงกัน:

GET /reports/42 HTTP/1.1
Accept: text/csv, application/json;q=0.8
Accept-Language: th, en;q=0.5

ค่า q คือน้ำหนักด้านคุณภาพ (quality weight) — ในที่นี้ client อยากได้ CSV มากกว่า ถัดมาจึงเป็น JSON ฝั่ง server ควรเลือก type ที่ดีที่สุดเท่าที่รองรับได้ แล้วประกาศกลับมาใน Content-Type

  • หาก server ไม่สามารถสร้าง type ใดที่ยอมรับได้เลย ให้ตอบ 406 Not Acceptable
  • หาก body ของ request มาในรูปแบบ type ที่ server แยกวิเคราะห์ (parse) ไม่ได้ ให้ตอบ 415 Unsupported Media Type
JavaScript
ข้อดี (Content Negotiation)ข้อแลกเปลี่ยน
API เดียว รองรับหลาย format (JSON, XML, CSV)server ต้อง implement serializer หลายตัว
client บอก server ว่าต้องการ format อะไรcomplexity เพิ่ม — content type routing logic
versioning ผ่าน media type ที่ RESTful ที่สุดtooling support สำหรับ custom media type น้อย
compression ผ่าน Accept-Encoding ลด bandwidthต้องระวัง cache key ที่ต้องรวม Accept header

ไม่ Return Content-Type ใน Response อาการ:

  • server return JSON แต่ไม่ตั้ง Content-Type: application/json
  • client ไม่รู้วิธี parse body — บาง client ถือว่าเป็น plain text
  • ตั้ง Content-Type ทุก response ที่มี body เสมอ

Cache โดยไม่รวม Accept ใน Cache Key อาการ:

  • CDN cache response ของ GET /reports ที่ขอ JSON
  • request ถัดไปขอ CSV — CDN return JSON เดิม
  • ตั้ง Vary: Accept header เพื่อให้ CDN รวม Accept ใน cache key

💡 ตัวอย่างจากของจริง

GitHub API:

  • Accept: application/vnd.github+json สำหรับ standard JSON
  • Accept: application/vnd.github.raw สำหรับ raw file content
  • format ต่างกันผ่าน Accept header โดยไม่ต้องเปลี่ยน URI

AWS API:

  • Accept-Encoding: gzip — response body compress อัตโนมัติ
  • ลด bandwidth สำหรับ large JSON response เช่น list operation
client ใช้ header ใดในการร้องขอรูปแบบของ representation?
server ไม่รองรับ type ใดเลยใน Accept ควรใช้ status ใด?
body ของ request มาในรูปแบบ media type ที่ server แยกวิเคราะห์ไม่ได้ ควรใช้ status ใด?