Caching และ ETags
HTTP มีโมเดล caching ที่ทรงพลังติดตัวมาอยู่แล้ว ถ้าใช้เป็น client (หรือ CDN) จะไม่ต้องดาวน์โหลดข้อมูลที่ไม่ได้เปลี่ยนซ้ำอีก และนี่มักเป็นการเพิ่ม performance ก้อนใหญ่ที่สุดที่ API หนึ่งตัวจะได้รับ
Cache-Control: นี่จะ fresh นานแค่ไหน?
หัวข้อที่มีชื่อว่า “Cache-Control: นี่จะ fresh นานแค่ไหน?”Cache-Control บอก cache ว่า response สามารถนำกลับมาใช้ซ้ำได้หรือไม่และนานเท่าใด:
Cache-Control: public, max-age=60 # any cache may reuse for 60sCache-Control: private, max-age=0 # only the client, must revalidateCache-Control: no-store # never cache (sensitive data)ตราบใดที่ response ยัง fresh อยู่ client จะหยิบของเดิมมาใช้ซ้ำโดยไม่ส่ง request เลย ต่อเมื่อกลายเป็น stale แล้วจึงจะ revalidate
ETag + If-None-Match: ข้อมูลเปลี่ยนหรือยัง?
หัวข้อที่มีชื่อว่า “ETag + If-None-Match: ข้อมูลเปลี่ยนหรือยัง?”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)
Last-Modified + If-Modified-Since คือคู่เทียบเท่าที่อิง timestamp แต่ ETag แม่นยำกว่า เพราะจับการเปลี่ยนแปลงได้ทุกแบบ ไม่ใช่แค่ที่ละเอียดถึงระดับวินาที
การคำนวณ ETag
หัวข้อที่มีชื่อว่า “การคำนวณ ETag”| Cache Mechanism | ทำงานอย่างไร | เหมาะกับ |
|---|---|---|
Cache-Control: max-age=3600 | browser cache นาน 1 ชั่วโมง | static resource, slow-changing data |
ETag + If-None-Match | server return 304 ถ้า resource ไม่เปลี่ยน | resource ที่เปลี่ยนบ้าง |
Last-Modified + If-Modified-Since | ใช้ timestamp แทน hash | resource ที่รู้ 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 ไฟล์จำนวนมากได้อย่างมีประสิทธิภาพ