การแคช API ด้วย ETag และ Cache-Control: คำขอแบบมีเงื่อนไขช่วยลดปริมาณข้อมูลได้อย่างไร

เรียนรู้วิธีที่เฮดเดอร์ Cache-Control และการตรวจสอบ ETag ทำให้การเรียกใช้ API ซ้ำตอบกลับด้วย 304 responses, ป้องกันการอัปเดตที่สูญหายด้วย If-Match และลดขนาดเพย์โหลด

Ashley Goolam

Ashley Goolam

31 August 2026

การแคช API ด้วย ETag และ Cache-Control: คำขอแบบมีเงื่อนไขช่วยลดปริมาณข้อมูลได้อย่างไร

Apidog สำหรับองค์กร

การติดตั้งแบบ On-Premises

SSO & RBAC

รองรับมาตรฐาน SOC 2

สำรวจ Apidog Enterprise

API ของคุณอาจส่ง JSON เดียวกันหลายพันครั้งต่อวัน ลูกค้าขอ GET /v1/products/42 และได้รับข้อมูล 18 KB กลับมา หลังจากนั้นห้านาที ลูกค้าขออีกครั้งและได้รับข้อมูล 18 KB เดิมกลับมาอีกครั้ง ไม่มีอะไรเปลี่ยนแปลง แต่คุณก็ยังคงต้องจ่ายค่าแบนด์วิดท์, การแปลงข้อมูล (serialization), และการอ่านจากฐานข้อมูลอยู่ดี

HTTP ได้แก้ปัญหานี้แล้ว ส่วนหัว (header) Cache-Control จะบอกไคลเอนต์ว่าการตอบสนองจะยังคงสดใหม่ได้นานแค่ไหน ส่วนหัว ETag จะให้ลายนิ้วมือ (fingerprint) เพื่อให้ไคลเอนต์ตรวจสอบว่ามีการเปลี่ยนแปลงหรือไม่ เมื่อรวมกันแล้ว สิ่งเหล่านี้จะเปลี่ยนคำขอซ้ำๆ ให้เป็นการตอบสนองแบบ 304 Not Modified ที่มีเนื้อหาว่างเปล่า และยังช่วยป้องกันการอัปเดตที่สูญหายจากการเขียนข้อมูลได้อีกด้วย แนวคิดเดียวกันนี้ยังขับเคลื่อนรูปแบบฝั่งไคลเอนต์ด้วย หากคุณได้อ่านคู่มือของเราเกี่ยวกับการ แคชการตอบสนอง API ใน React บทความนี้คือส่วนฝั่งเซิร์ฟเวอร์ของเรื่องราวนั้น

คู่มือนี้จะอธิบายถึงสามเลเยอร์ของการแคช HTTP, แสดงขั้นตอนการทำงานของ 304 แบบไปกลับอย่างละเอียด, คลายความสับสนระหว่าง no-cache กับ no-store, และปิดท้ายด้วยโค้ด Express ที่ใช้งานได้จริง คุณจะได้เรียนรู้วิธีตรวจสอบทั้งหมดนี้ใน Apidog โดยการส่งส่วนหัวแบบมีเงื่อนไขและยืนยันการตอบสนอง 304 ด้วยตัวคุณเอง

ปุ่ม

สามเลเยอร์ของการแคช HTTP

การแคช HTTP สำหรับ API แบ่งออกเป็นสามการตัดสินใจที่แยกจากกัน ทีมมักจะประสบปัญหาเมื่อนำแนวคิดเหล่านี้มาปะปนกัน

เลเยอร์ 1: ความสดใหม่ (Freshness). ไคลเอนต์สามารถใช้การตอบสนองซ้ำได้นานแค่ไหนโดยไม่ต้องถามคุณเลย? นั่นคือ Cache-Control: max-age=60 เป็นเวลา 60 วินาที ไคลเอนต์จะให้บริการสำเนาที่แคชไว้ในเครื่อง ไม่มีปริมาณการรับส่งข้อมูลเครือข่าย นี่คือการใช้แคชที่ถูกที่สุดเท่าที่จะเป็นไปได้ และยังมีความเสี่ยงที่สุดด้วย เพราะไคลเอนต์ไม่สามารถตรวจจับการเปลี่ยนแปลงได้จนกว่าเวลาจะหมดลง

เลเยอร์ 2: การตรวจสอบ (Validation). เมื่อการตอบสนองเก่า (stale) แล้ว ไคลเอนต์ไม่จำเป็นต้องดาวน์โหลดซ้ำ ไคลเอนต์จะถามว่า "มีการเปลี่ยนแปลงหรือไม่?" โดยการส่งลายนิ้วมือที่คุณให้ไว้ก่อนหน้านี้ หากทรัพยากรไม่มีการเปลี่ยนแปลง คุณจะตอบกลับด้วย 304 Not Modified และไม่มีเนื้อหา ETag ที่ใช้คู่กับ If-None-Match คือเวอร์ชันที่แม่นยำของสิ่งนี้ ส่วน Last-Modified ที่ใช้คู่กับ If-Modified-Since คือเวอร์ชันเก่ากว่าที่อิงตามเวลา โดยมีความละเอียดระดับวินาที

เลเยอร์ 3: การทำให้เป็นโมฆะ (Invalidation). เมื่อข้อมูลเปลี่ยนแปลง สำเนาที่เก่าจะหมดอายุได้อย่างไร? แคชส่วนตัวของไคลเอนต์จะหมดอายุเองตาม max-age แคชที่ใช้ร่วมกันและ CDN ต้องการการล้างข้อมูลอย่างชัดเจน (explicit purges), TTL ที่สั้น, หรือคำสั่งเช่น stale-while-revalidate ที่จำกัดระยะเวลาความเก่า

ความสดใหม่ช่วยประหยัดได้มากที่สุด การตรวจสอบจะตรวจจับทุกสิ่งที่ความสดใหม่พลาดไป และการทำให้เป็นโมฆะจะรักษาความถูกต้องของทั้งสองอย่าง API ส่วนใหญ่ต้องการทั้งสามสิ่งนี้

การทำงานของ 304 Not Modified แบบไปกลับ

นี่คือวัฏจักรทั้งหมดสำหรับเอนด์พอยต์สินค้า ทีละขั้นตอน

คำขอแรก. ไคลเอนต์ยังไม่มีอะไรที่แคชไว้:

GET /v1/products/42 HTTP/1.1
Host: api.example.com

การตอบสนองแรก. คุณส่งคืนเนื้อหาพร้อมกับข้อมูลเมตาของการแคช:

HTTP/1.1 200 OK
Cache-Control: private, max-age=60
ETag: "33a64df551425fcc55e4d42a148795d9f2"
Content-Type: application/json
Content-Length: 18432

ไคลเอนต์จัดเก็บเนื้อหาและ ETag เป็นเวลา 60 วินาทีถัดไป ไคลเอนต์จะไม่ติดต่อคุณเลย

คำขอครั้งที่สอง หลังจาก 60 วินาที. สำเนาข้อมูลเก่า (stale) แล้ว ดังนั้นไคลเอนต์จึงทำการตรวจสอบความถูกต้องใหม่:

GET /v1/products/42 HTTP/1.1
Host: api.example.com
If-None-Match: "33a64df551425fcc55e4d42a148795d9f2"

การตอบสนองครั้งที่สอง ทรัพยากรไม่มีการเปลี่ยนแปลง. เซิร์ฟเวอร์ของคุณจะเปรียบเทียบ ETag ที่ส่งมากับ ETag ปัจจุบัน หากตรงกัน:

HTTP/1.1 304 Not Modified
Cache-Control: private, max-age=60
ETag: "33a64df551425fcc55e4d42a148795d9f2"

ไม่มีเนื้อหาการตอบกลับ แทนที่จะเป็น 18 KB การตอบสนองจะเป็นเพียงส่วนหัวไม่กี่ร้อยไบต์ ไคลเอนต์จะทำเครื่องหมายสำเนาที่แคชไว้ว่าสดใหม่ไปอีก 60 วินาทีและนำไปใช้งาน หากผลิตภัณฑ์มีการเปลี่ยนแปลง คุณจะส่งคืนรหัส 200 ปกติพร้อมเนื้อหาใหม่และ ETag ใหม่ เราได้กล่าวถึงรหัสสถานะนี้โดยละเอียดใน คำอธิบาย 304 Not Modified ของเรา สรุปสั้นๆ คือ 304 เป็นคำสั่งแคช ไม่ใช่ข้อผิดพลาด

หลักเศรษฐศาสตร์นั้นง่าย คำขอ GET แบบมีเงื่อนไขยังคงต้องใช้การเดินทางไปกลับ (round trip) บวกกับงานที่ใช้ในการคำนวณ ETag ปัจจุบัน สิ่งที่ถูกลดลงคือการถ่ายโอนข้อมูล (payload transfer) และการแยกวิเคราะห์ข้อมูลฝั่งไคลเอนต์ใหม่ (client-side re-parsing) สำหรับเอนด์พอยต์รายการขนาดใหญ่ที่ถูกเรียกใช้โดยไคลเอนต์มือถือ วิธีนี้ช่วยลดปริมาณข้อมูล API ขาออกได้ถึง 60 ถึง 90 เปอร์เซ็นต์เป็นประจำ

คำสั่ง Cache-Control ที่สำคัญสำหรับ API

Cache-Control มีคำสั่งมากกว่าหนึ่งโหล สำหรับ JSON API มีห้าคำสั่งที่สำคัญที่สุด

no-store เทียบกับ no-cache. นี่คือข้อผิดพลาดการแคชที่พบบ่อยที่สุดใน API ที่ใช้งานจริง และเกิดขึ้นได้ทั้งสองทาง no-store หมายถึง "ห้ามเขียนสิ่งนี้ลงในแคชใดๆ เด็ดขาด" ใช้สำหรับข้อมูลที่มีความละเอียดอ่อนอย่างแท้จริง: โทเค็น, ข้อมูลธนาคาร, ข้อมูล PII ที่คุณต้องไม่เก็บถาวร no-cache มีความหมายเกือบตรงข้ามกับที่ฟังดู: แคชอาจเก็บการตอบสนองได้ แต่ต้องตรวจสอบความถูกต้องกับต้นทางก่อนนำกลับมาใช้ใหม่ทุกครั้ง เมื่อใช้ร่วมกับ ETag, no-cache จะช่วยให้คุณประหยัดค่าใช้จ่ายจากการตอบสนอง 304 ในทุกคำขอ ในขณะที่รับประกันว่าไคลเอนต์จะไม่แสดงข้อมูลที่ล้าสมัย ทีมที่ใช้ no-store กับทุกสิ่ง "เพื่อความปลอดภัย" กำลังปิดการใช้งานคำขอแบบมีเงื่อนไขทั้งหมด และต้องจ่ายค่าใช้จ่ายเต็มรูปแบบสำหรับข้อมูล (payload) ในทุกๆ การเรียกใช้

private. กำหนดให้การตอบสนองสามารถแคชได้โดยไคลเอนต์ของผู้ใช้ปลายทางเท่านั้น ห้ามแคชโดยแคชที่ใช้ร่วมกันหรือ CDN การตอบสนองใดๆ ที่แตกต่างกันไปสำหรับผู้ใช้แต่ละคน ซึ่งส่วนใหญ่เป็นการรับส่งข้อมูล API ที่ต้องยืนยันตัวตน ควรสั่งให้เป็น private หากไม่มีสิ่งนี้ พร็อกซีที่กำหนดค่าผิดพลาดอาจส่งข้อมูลบัญชีของผู้ใช้คนหนึ่งไปให้อีกคนหนึ่งได้

max-age. อายุความสดใหม่เป็นวินาที สำหรับ API ให้คิดถึงค่าที่น้อย: 30 ถึง 300 วินาทีครอบคลุมเอนด์พอยต์การอ่านส่วนใหญ่ คุณไม่ได้พยายามที่จะลดคำขอเป็นเวลาหนึ่งวัน แต่คุณกำลังพยายามรองรับการรับส่งข้อมูลที่พุ่งสูงขึ้นและวงจรการเรียกซ้ำ

stale-while-revalidate. ทางออกที่ปฏิบัติได้จริง Cache-Control: max-age=60, stale-while-revalidate=300 บอกแคชว่า: ให้บริการสำเนาที่เก่าแล้ว (stale copy) ได้สูงสุดอีก 5 นาที แต่ให้ทำการรีเฟรชข้อมูลในเบื้องหลัง ผู้ใช้จะได้รับการตอบสนองทันที และต้นทางของคุณจะได้รับการอัปเดตหลังจากนั้นไม่นาน CDN อย่าง Cloudflare และ Fastly รวมถึงเว็บเบราว์เซอร์ต่างก็รองรับสิ่งนี้

ค่าเริ่มต้นที่สมเหตุสมผลสำหรับเอนด์พอยต์การอ่านที่ต้องมีการยืนยันตัวตนจะมีลักษณะดังนี้:

Cache-Control: private, max-age=60, stale-while-revalidate=120
ETag: "9f8b2c41aa73e0d5"

ข้อกำหนดพฤติกรรมฉบับเต็มอยู่ใน RFC 9111 ซึ่งเข้ามาแทนที่ RFC 7234 ในฐานะเอกสารอ้างอิงการแคช HTTP ที่ชัดเจนที่สุด เมื่อ CDN มีพฤติกรรมที่ทำให้คุณประหลาดใจ RFC นั้นคือที่ที่คุณจะพบคำตอบ

ETag แบบแข็งแกร่ง (Strong) เทียบกับ ETag แบบอ่อนแอ (Weak)

ETag มีสองประเภท และคำนำหน้า W/ ใช้แยกระหว่างสองประเภทนี้

Strong ETag (ETag: "33a64df551425fcc") รับประกันความเท่าเทียมกันแบบไบต์ต่อไบต์ การตอบสนองสองรายการที่มี Strong ETag เดียวกันถือว่าเหมือนกัน ซึ่งทำให้ Strong ETag ปลอดภัยสำหรับคำขอแบบ byte-range และจำเป็นสำหรับการควบคุมการทำงานพร้อมกัน (concurrency control) ด้วย If-Match

Weak ETag (ETag: W/"33a64df551425fcc") รับประกันความเท่าเทียมกันทางความหมาย (semantic equivalence) ไบต์อาจแตกต่างกันไป อาจเป็นลำดับฟิลด์เปลี่ยนไป หรือฟิลด์เวลาเปลี่ยนไป แต่ความหมายยังคงเหมือนเดิม ดังนั้นแคชจึงสามารถเก็บสำเนาไว้ได้

ปัญหาที่พบ: มิดเดิลแวร์การบีบอัดข้อมูล (compression middleware) Nginx และเฟรมเวิร์กบางตัวจะเขียน Strong ETag ใหม่เป็น Weak ETag เมื่อทำการบีบอัดการตอบสนองแบบ gzip ทันที เนื่องจากไบต์ที่ถูกบีบอัดจะไม่ตรงกับต้นฉบับอีกต่อไป หากการตรวจสอบการทำงานพร้อมกันของคุณล้มเหลวอย่างลึกลับหลังพร็อกซี ให้มองหาคำนำหน้า W/ ที่ไม่ได้อยู่ที่นั่นเมื่อแอปเซิร์ฟเวอร์ของคุณส่งการตอบสนอง

ควรใช้ Strong ETag ที่คำนวณจากเนื้อหาที่ยังไม่ได้บีบอัดเป็นค่าเริ่มต้น ใช้ Weak ETag เฉพาะเมื่อคุณทราบว่ามีการให้บริการข้อมูลเดียวกันในรูปแบบที่แตกต่างกัน

การสร้าง ETag: แฮชของเนื้อหา (body hash) เทียบกับคอลัมน์เวอร์ชัน (version column)

มีสองกลยุทธ์หลัก และกลยุทธ์ที่เหมาะสมขึ้นอยู่กับว่าต้นทุนอยู่ที่จุดใด

แฮชของเนื้อหาการตอบสนอง (Hash of the response body). ทำการแปลงข้อมูล (serialize) การตอบสนอง จากนั้นแฮช (MD5 หรือ SHA-1 ก็เพียงพอสำหรับกรณีนี้; นี่คือลายนิ้วมือ ไม่ใช่ขอบเขตความปลอดภัย) และใส่เครื่องหมายคำพูด มันมีความแม่นยำตั้งแต่เริ่มต้นและไม่จำเป็นต้องเปลี่ยน schema ข้อเสียคือ: คุณจะต้องสร้างการตอบสนองเต็มรูปแบบทุกครั้งที่รับคำขอ รวมถึง 304s คุณประหยัดแบนด์วิดท์แต่ไม่ได้ประหยัดการคำนวณหรือโหลดฐานข้อมูล

คอลัมน์เวอร์ชัน (Version column) หรือ updated_at. ดึง ETag มาจากข้อมูลที่คุณสามารถดึงมาใช้ได้ง่ายและราคาถูก: ETag: "42-v17" จากตัวนับเวอร์ชันของแถว หรือแฮชของ updated_at ตอนนี้คำขอแบบมีเงื่อนไขจะใช้การค้นหาแบบอินเด็กซ์เพียงครั้งเดียวแทนการแปลงข้อมูลเต็มรูปแบบ ข้อควรระวัง: เวอร์ชันจะต้องเพิ่มขึ้นทุกครั้งที่มีการเปลี่ยนแปลงที่ส่งผลต่อการตอบสนอง รวมถึงการเปลี่ยนแปลงในตารางที่เชื่อมโยงกัน หากพลาดไป คุณจะส่ง 304 ที่ล้าสมัย ซึ่งเป็นข้อผิดพลาดในการแคชที่แย่ที่สุดเพราะมองไม่เห็น

เริ่มต้นด้วยการแฮชเนื้อหา (body hashing) โดยค่าเริ่มต้นจะถูกต้อง ย้ายเอนด์พอยต์ที่ใช้งานหนัก (hot endpoints) ไปใช้ ETag แบบเวอร์ชันเมื่อการวิเคราะห์โปรไฟล์แสดงให้เห็นว่าต้นทุนการแปลงข้อมูล (serialization cost) มีความสำคัญ

ETag สำหรับการทำงานพร้อมกันแบบมองโลกในแง่ดี (optimistic concurrency): If-Match และ 412

ลายนิ้วมือเดียวกันที่ช่วยประหยัดแบนด์วิดท์ในการอ่าน ยังช่วยป้องกันการอัปเดตที่สูญหายในการเขียนข้อมูลได้อีกด้วย

ปัญหาการอัปเดตที่สูญหาย (lost update problem): ผู้ดูแลระบบสองคนโหลดสินค้าหมายเลข 42 พร้อมกัน ผู้ดูแลระบบ A เปลี่ยนราคาและบันทึก ผู้ดูแลระบบ B แก้ไขคำผิดและบันทึกในอีก 30 วินาทีต่อมา โดยเขียนทับการเปลี่ยนราคาของ A ด้วยราคาเก่าที่ B โหลดมา ไม่มีใครเห็นข้อผิดพลาด ข้อมูลนั้นผิดพลาดอย่างเงียบๆ

วิธีแก้คือการทำให้การอัปเดตทุกครั้งมีเงื่อนไขตามเวอร์ชันที่ไคลเอนต์เห็นล่าสุด:

PUT /v1/products/42 HTTP/1.1
If-Match: "33a64df551425fcc55e4d42a148795d9f2"
Content-Type: application/json

เซิร์ฟเวอร์จะเปรียบเทียบ If-Match กับ ETag ปัจจุบันของทรัพยากร หากตรงกัน: ทำการอัปเดต, คืนค่า 200 พร้อม ETag ใหม่ หากไม่ตรงกัน แสดงว่ามีคนอื่นเข้ามาทำก่อน: ปฏิเสธด้วย 412 Precondition Failed และไม่แตะต้องข้อมูลนั้น ไคลเอนต์จะดึงข้อมูลใหม่, นำการเปลี่ยนแปลงของตนไปใช้กับเวอร์ชันที่สดใหม่, แล้วลองใหม่อีกครั้ง API ที่เข้มงวดจะไปไกลกว่านั้นและส่งคืน 428 Precondition Required สำหรับคำสั่ง PUT ใดๆ ที่ละเว้น If-Match ทำให้การตรวจสอบความปลอดภัยนี้เป็นข้อบังคับ

การเพิ่มสิ่งนี้แทบไม่มีค่าใช้จ่ายเลยเมื่อมี ETag อยู่แล้ว และมันจะเปลี่ยนข้อผิดพลาดข้อมูลเสียหายที่เงียบงันให้เป็นสถานะ HTTP ที่ชัดเจนและสามารถลองใหม่ได้

สิ่งที่ CDN และพร็อกซีทำกับส่วนหัวเหล่านี้

แคชที่ใช้ร่วมกัน (shared caches) จะอยู่ระหว่างต้นทางของคุณและไคลเอนต์ของคุณ และพวกมันจะอ่านส่วนหัวเดียวกันตามกฎของตัวเอง

ตัวอย่าง Express: การส่งคืน ETag และการจัดการ If-None-Match

Express ตั้งค่า Weak ETag ด้วยตัวเอง แต่การจัดการด้วยตนเองจะให้ Strong ETag พร้อมกับเส้นทางสำหรับการเขียนข้อมูล 412:

import crypto from "node:crypto";
import express from "express";

const app = express();
app.use(express.json());

function etagFor(payload) {
  const hash = crypto.createHash("sha1")
    .update(JSON.stringify(payload))
    .digest("hex");
  return `"${hash}"`;
}

app.get("/v1/products/:id", async (req, res) => {
  const product = await db.products.find(req.params.id);
  const etag = etagFor(product);

  res.set("Cache-Control", "private, max-age=60, stale-while-revalidate=120");
  res.set("ETag", etag);

  if (req.get("If-None-Match") === etag) {
    return res.status(304).end();   // fingerprint matches: no body
  }
  res.json(product);
});

app.put("/v1/products/:id", async (req, res) => {
  const product = await db.products.find(req.params.id);
  const currentEtag = etagFor(product);
  const ifMatch = req.get("If-Match");

  if (!ifMatch) {
    return res.status(428).json({ error: "If-Match header required" });
  }
  if (ifMatch !== currentEtag) {
    return res.status(412).json({ error: "Resource changed since you fetched it" });
  }

  const updated = await db.products.update(req.params.id, req.body);
  res.set("ETag", etagFor(updated));
  res.json(updated);
});

โปรดสังเกตว่าส่วนการทำงานของ 304 ยังคงส่งส่วนหัว Cache-Control และ ETag ตาม RFC 9111 การตอบสนอง 304 จะอัปเดตข้อมูลเมตาของการตอบสนองที่จัดเก็บไว้ ดังนั้นให้ส่งสิ่งที่ไคลเอนต์ต้องการเพื่อรักษาสำเนาให้สดใหม่อีกครั้ง

การตรวจสอบพฤติกรรมการแคชใน Apidog

โค้ดที่ดูเหมือนถูกต้องยังคงอาจแคชผิดพลาดได้เมื่อมิดเดิลแวร์และพร็อกซีเข้ามาเกี่ยวข้อง ให้ทดสอบที่ระดับ HTTP ไม่ใช่ระดับโค้ด

ใน Apidog การตรวจสอบด้วยตนเองใช้เวลาประมาณหนึ่งนาที:

  1. ส่ง GET /v1/products/42 แล้วเปิดแผงส่วนหัวของการตอบสนอง ยืนยันว่ามี ETag และ Cache-Control อยู่ และ ETag อยู่ในเครื่องหมายคำพูด คัดลอกค่า ETag
  2. ในคำขอเดียวกัน ให้เพิ่มส่วนหัว If-None-Match ด้วยค่าที่คัดลอกมาแล้วส่งอีกครั้ง คุณควรได้รับการตอบสนอง 304 พร้อมเนื้อหาว่างเปล่า หากคุณยังคงได้รับ 200 แสดงว่าเลเยอร์การตรวจสอบของคุณไม่ได้เปรียบเทียบลายนิ้วมือ
  3. เปลี่ยนเรคคอร์ด ส่งซ้ำ และยืนยันว่าคุณกลับมาที่ 200 พร้อม ETag ที่สดใหม่

เพื่อให้สิ่งนี้ทำงานได้หลังจากทุกการ deploy ให้เชื่อมโยงขั้นตอนเดียวกันนี้เข้ากับสถานการณ์การทดสอบ เชื่อมโยงคำขอสองรายการ: รายการแรกดึง ETag จากส่วนหัวของการตอบสนองไปเก็บในตัวแปร รายการที่สองส่งกลับไปเป็น If-None-Match และยืนยันว่าสถานะเท่ากับ 304 และเนื้อหาว่างเปล่า เพิ่มขั้นตอนที่สามสำหรับเส้นทางการเขียน: ส่ง PUT ด้วยค่า If-Match ที่ล้าสมัยโดยเจตนา เช่น "deadbeefcafe1234" และยืนยันว่าได้ 412 คู่มือของเราเกี่ยวกับ การยืนยัน API (API assertions) ครอบคลุมไวยากรณ์การยืนยันสำหรับรหัสสถานะและส่วนหัว

เรียกใช้สถานการณ์นั้นใน CI และการอัปเกรดมิดเดิลแวร์ที่ลบ ETag ของคุณอย่างเงียบๆ จะกลายเป็นไปป์ไลน์ที่ล้มเหลว แทนที่จะเป็นค่าใช้จ่ายแบนด์วิดท์ ดาวน์โหลด Apidog ฟรีและสร้างสถานการณ์จำลองกับเอนด์พอยต์ของคุณเอง; ใช้เวลาอ่านนานกว่าการคลิกประกอบเข้าด้วยกัน

คำถามที่พบบ่อย

ความแตกต่างระหว่าง no-cache และ no-store คืออะไร?

no-store ห้ามการแคชโดยสมบูรณ์: ไม่มีสิ่งใดถูกเขียนลงดิสก์หรือหน่วยความจำ ดังนั้นทุกคำขอจึงต้องดาวน์โหลดการตอบสนองแบบเต็ม no-cache อนุญาตให้จัดเก็บได้ แต่บังคับให้ตรวจสอบความถูกต้องใหม่ก่อนการนำกลับมาใช้ใหม่แต่ละครั้ง ดังนั้นเมื่อใช้คู่กับ ETag ก็ยังคงให้การตอบสนอง 304 และประหยัดข้อมูลได้ ใช้ no-store สำหรับข้อมูลที่ละเอียดอ่อนเท่านั้น การใช้มันในทุกที่ถือเป็นข้อผิดพลาด Cache-Control ที่มีค่าใช้จ่ายสูงที่สุดที่ทีม API สามารถทำได้

ETag ใช้ได้กับ POST หรือไม่?

ส่วนใหญ่แล้วไม่ และเป็นไปตามการออกแบบ ETag อธิบายสถานะของทรัพยากรที่ URL และ POST มักจะสร้างสิ่งใหม่มากกว่าการอ่านสถานะที่เสถียร ในทางปฏิบัติ แคชไม่ได้แคชการตอบสนองจาก POST ส่วนหัวแบบมีเงื่อนไขที่สำคัญสำหรับการเขียนคือ If-Match บน PUT, PATCH และ DELETE ซึ่ง ETag ทำหน้าที่ป้องกันการอัปเดตที่สูญหาย หากคุณพยายามแคชการตอบสนองจาก POST นั่นมักจะเป็นสัญญาณว่าการดำเนินการนั้นควรจะเป็น GET

การตอบสนอง 304 ทำให้ API ของฉันเร็วขึ้นหรือไม่?

มันทำให้การถ่ายโอนข้อมูลมีขนาดเล็กลง ซึ่งไม่ใช่สิ่งเดียวกัน เซิร์ฟเวอร์ยังคงรับคำขอ, ทำการตรวจสอบสิทธิ์ (auth), และคำนวณ ETag ปัจจุบัน ดังนั้นการประหยัด CPU ของต้นทางจึงขึ้นอยู่กับว่าคุณสามารถสร้างลายนิ้วมือนั้นได้ถูกแค่ไหน ประโยชน์ที่ได้รับจะแสดงให้เห็นในแบนด์วิดท์, แบตเตอรี่มือถือ, และเวลาในการเรนเดอร์บนเครือข่ายที่ช้า วัดผลก่อนและหลัง; คู่มือการทดสอบประสิทธิภาพ API ของเราแสดงวิธีการวัด latency และ throughput เพื่อให้คุณสามารถพิสูจน์ความแตกต่างได้แทนที่จะคาดเดา

ฉันควรใช้ ETag หรือ Last-Modified?

ส่งทั้งสองอย่างเมื่อทำได้ ETag มีความแม่นยำมากกว่า: สามารถตรวจจับการเปลี่ยนแปลงที่เกิดขึ้นภายในวินาทีและข้อแตกต่างในระดับเนื้อหาที่ timestamp อาจพลาดไป และ If-None-Match จะมีความสำคัญเหนือกว่า If-Modified-Since เมื่อทั้งสองอย่างมาพร้อมกัน Last-Modified ยังคงมีประโยชน์ในฐานะกลไกสำรองสำหรับไคลเอนต์รุ่นเก่า และเป็น heuristic ที่แคชบางตัวใช้ในการประมาณความสดใหม่ หากคุณจะส่งเพียงอย่างเดียว ให้ส่ง ETag

ฝึกการออกแบบ API แบบ Design-first ใน Apidog

ค้นพบวิธีที่ง่ายขึ้นในการสร้างและใช้ API