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

Caching และ ETags

HTTP มีโมเดล caching ที่ทรงพลังติดตัวมาอยู่แล้ว ถ้าใช้เป็น client (หรือ CDN) จะไม่ต้องดาวน์โหลดข้อมูลที่ไม่ได้เปลี่ยนซ้ำอีก และนี่มักเป็นการเพิ่ม performance ก้อนใหญ่ที่สุดที่ API หนึ่งตัวจะได้รับ

Cache-Control บอก cache ว่า response สามารถนำกลับมาใช้ซ้ำได้หรือไม่และนานเท่าใด:

Cache-Control: public, max-age=60 # any cache may reuse for 60s
Cache-Control: private, max-age=0 # only the client, must revalidate
Cache-Control: no-store # never cache (sensitive data)

ตราบใดที่ response ยัง fresh อยู่ client จะหยิบของเดิมมาใช้ซ้ำโดยไม่ส่ง request เลย ต่อเมื่อกลายเป็น stale แล้วจึงจะ revalidate

ETag คือ validator — ลายนิ้วมือของ representation ปัจจุบัน ใน request ถัดไป client จะส่งค่านี้กลับมาใน If-None-Match ถ้ายังตรงกันอยู่ server จะคืน 304 Not Modified โดยไม่มี body:

sequenceDiagram
  participant C as Client
  participant S as Server
  C->>S: GET /articles/42
  S-->>C: 200 OK + ETag: "v7"
  Note over C: later...
  C->>S: GET /articles/42 (If-None-Match: "v7")
  S-->>C: 304 Not Modified (no body)
ETag ที่ตรงกันเปลี่ยน response เต็มรูปแบบให้กลายเป็น 304 เล็ก ๆ

Last-Modified + If-Modified-Since คือคู่เทียบเท่าที่อิง timestamp แต่ ETag แม่นยำกว่า เพราะจับการเปลี่ยนแปลงได้ทุกแบบ ไม่ใช่แค่ที่ละเอียดถึงระดับวินาที

JavaScript
Cache Mechanismทำงานอย่างไรเหมาะกับ
Cache-Control: max-age=3600browser cache นาน 1 ชั่วโมงstatic resource, slow-changing data
ETag + If-None-Matchserver return 304 ถ้า resource ไม่เปลี่ยนresource ที่เปลี่ยนบ้าง
Last-Modified + If-Modified-Sinceใช้ timestamp แทน hashresource ที่รู้ modified time ชัดเจน
Cache-Control: no-storeไม่ cache เลยsensitive data เช่น payment, user profile

Cache Sensitive Data โดยไม่ตั้งใจ อาการ:

  • Cache-Control: max-age=3600 บน /users/\{id\}/profile
  • browser หรือ CDN cache profile ของ user A ให้ user B เห็น
  • ตั้ง Cache-Control: no-store, private สำหรับ authenticated resource

ETag ที่ไม่ Stable อาการ:

  • ETag generate จาก timestamp — server ที่ต่างกัน generate ETag ต่างกันสำหรับ content เดียว
  • client ส่ง If-None-Match แต่ server return 200 ทุกครั้งแทน 304
  • generate ETag จาก hash ของ content แทน timestamp

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

GitHub API:

  • ETag บน resource ทุกตัว — conditional GET ลด bandwidth 90%+
  • rate limit ไม่นับ request ที่ return 304

AWS S3:

  • ETag คือ MD5 hash ของ object content
  • conditional GET ผ่าน If-None-Match ทำให้ sync ไฟล์จำนวนมากได้อย่างมีประสิทธิภาพ
response แบบ 304 Not Modified มีอะไรอยู่ข้างใน?
header ใดที่นำ validator ซึ่ง client ส่งกลับมาเพื่อ revalidate?
directive ของ Cache-Control ใดที่หมายความว่า "อย่าจัดเก็บ response นี้เลย"?