การเข้าใจการตอบสนอง 304 Not Modified ในการจัดเก็บแคช HTTP

เมื่อพัฒนาแอปพลิเคชันเว็บ การจัดการทรัพยากรอย่างมีประสิทธิภาพนั้นสำคัญต่อประสิทธิภาพโดยเฉพาะเมื่อเกี่ยวข้องกับการเข้าถึงไฟล์และการจัดเก็บแคชของเบราว์เซอร์ หนึ่งในวิธีในการปรับแต่งกระบวนการนี้คือการใช้การตอบสนอง 304 Not Modified HTTP อย่างถูกต้อง การตอบสนองนี้จะแจ้งให้เบราว์เซอร์ทราบว่าทรัพยากรที่ร้องขอนั้นไม่มีการเปลี่ยนแปลงตั้งแต่ครั้งสุดท้ายที่ดึงมา จึงทำให้เบราว์เซอร์สามารถใช้เวอร์ชันที่เก็บแคชไว้แทนการดาวน์โหลดอีกครั้ง แต่คุณจะรู้ได้อย่างไรว่าควรจะส่งการตอบสนองนี้เมื่อใด? มาตีแผ่กันเป็นขั้นตอน

ส่วนหัว HTTP ที่ควรตรวจสอบ

เพื่อที่จะตัดสินใจว่าสามารถส่งการตอบสนอง 304 Not Modified ได้หรือไม่ คุณต้องตรวจสอบส่วนหัว HTTP เฉพาะที่ถูกส่งโดยเบราว์เซอร์ของลูกค้า ส่วนหัวหลัก 2 ตัวที่ควรให้ความสนใจได้แก่:

  1. Etag: ส่วนหัวนี้ทำหน้าที่เป็นตัวระบุเฉพาะสำหรับทรัพยากรในเวอร์ชันที่เฉพาะเจาะจง เบราว์เซอร์จะเปรียบเทียบ Etag ที่เก็บแคชไว้กับ Etag ของเซิร์ฟเวอร์เพื่อตรวจสอบว่าตรงกันหรือไม่
  2. If-None-Match: ส่วนหัวนี้ถูกส่งโดยเบราว์เซอร์และมีค่า Etag ที่เก็บแคชไว้ หากทรัพยากรไม่มีการเปลี่ยนแปลง เซิร์ฟเวอร์สามารถตอบสนองด้วย 304 ได้

สิ่งที่ควรสังเกต

  • ถ้า Etag จากเบราว์เซอร์มีอยู่: หากเบราว์เซอร์รวมทั้งส่วนหัว Etag หรือ If-None-Match ในคำขอ แสดงว่ามันมีเวอร์ชันที่ถูกเก็บแคชไว้ก่อนหน้านี้
  • ข้อพิจารณาเกี่ยวกับการอ้างอิง: บางครั้งเบราว์เซอร์จะใส่เครื่องหมายอ้างอิงไว้ในค่าของ Etag อย่าลืมลบเครื่องหมายอ้างอิงเหล่านี้ออกก่อนการเปรียบเทียบ

ส่วนหัวที่จำเป็นสำหรับการตอบสนองครั้งแรก

เมื่อส่งทรัพยากรในครั้งแรก (โดยปกติจะใช้การตอบสนอง 200 OK) เป็นสิ่งสำคัญที่จะต้องรวมส่วนหัวที่เกี่ยวข้องเพื่อแจ้งให้เบราว์เซอร์ทราบเกี่ยวกับสถานะของทรัพยากร:

  • Last-Modified: ระบุเวลาที่ทรัพยากรถูกเปลี่ยนแปลงครั้งสุดท้าย ซึ่งอาจเป็นการตรวจสอบเพิ่มเติมสำหรับการตรวจสอบแคชควบคู่กับ Etag
  • Etag (ตามที่กล่าวถึงก่อนหน้านี้): ค่านี้ควรถูกสร้างขึ้นสำหรับทรัพยากรและรวมอยู่ในส่วนหัวของการตอบสนองเพื่อช่วยในการตรวจสอบแคชในอนาคต

การนำตรรกะไปใช้

ต่อไปนี้เป็นตัวอย่าง pseudocode ที่ซับซ้อนน้อยลงซึ่งแสดงให้เห็นถึงวิธีการนำนโยบายไปใช้เพื่อส่งการตอบสนอง 304 Not Modified:

server_etag = gen_etag_for_this_file(myfile)
etag_from_browser = get_header("Etag")

if etag_from_browser does not exist:
    etag_from_browser = get_header("If-None-Match")
if the browser has quoted the etag:
    strip the quotes (e.g. "foo" --> foo)

set server_etag into http header

if etag_from_browser matches server_etag
    send 304 return code to browser

ตัวอย่างตรรกะของเซิร์ฟเวอร์

นี่คือตัวอย่างการนำตรรกะนี้ไปใช้ในเซิร์ฟเวอร์ของคุณ:

/* ลูกค้าควรกำหนด Etag หรือ If-None-Match */
mketag(etag, &sb);

etagin = apr_table_get(r->headers_in, "Etag");
if (etagin == NULL)
    etagin = apr_table_get(r->headers_in, "If-None-Match");
if (etag != NULL && etag[0] == '"') {
    /* ลบเครื่องหมายอ้างอิงถ้ามี */
    int sl; 
    sl = strlen(etag);
    memmove(etag, etag+1, sl+1);
    etag[sl-2] = 0;
}   

apr_table_add(r->headers_out, "ETag", etag);

if (etagin != NULL && strcmp(etagin, etag) == 0) {
    /* ถ้า etag ตรงกัน ให้คืนค่า 304 */
    rc = HTTP_NOT_MODIFIED;
}

ความคิดสุดท้าย

โดยการรู้วิธีและเวลาที่จะส่งการตอบสนอง 304 Not Modified คุณสามารถลดภาระของเซิร์ฟเวอร์ได้อย่างมีประสิทธิภาพและปรับปรุงประสบการณ์ของผู้ใช้ อย่าลืมความสำคัญของการรวมส่วนหัว Etag และ Last-Modified ในการตอบสนองครั้งแรกเพื่อให้ลูกค้าสามารถทำการร้องขอการตรวจสอบแคชอย่างถูกต้องในภายหลัง ถ้าคุณมีคำถามเกี่ยวกับการสร้าง Etag หรือจำเป็นต้องการความช่วยเหลือเพิ่มเติมในการนำไปใช้ อย่าลังเลที่จะติดต่อขอรายละเอียดเพิ่มเติมได้เลย สุขสันต์การเขียนโค้ด!