ส่วนหัวเพื่อป้องกันคำขอ 304 / If-modified-since / HEAD


31

ฉันควรส่งส่วนหัวใดให้หยุดการร้องขอทั้งหมดไปยังเซิร์ฟเวอร์ทันทีหลังจากที่เนื้อหาถูกแคช

เรามีเซิร์ฟเวอร์เวลาในการตอบสนองสูง (ถอนหายใจ, VMWare) ดังนั้นแม้การส่งHEADคำขอไปยังเซิร์ฟเวอร์จะใช้เวลา + 40ms

ขณะนี้เหล่านี้เป็นส่วนหัวที่ถูกส่ง / รับ;

ขอครั้งแรก

ลูกค้าส่ง;

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Pragma: no-cache, no-cache, no-cache
Cache-Control: no-cache, no-cache, no-cache

เซิร์ฟเวอร์ตอบสนอง;

HTTP/1.1 200 OK
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:51:51 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Last-Modified: Tue, 31 Jan 2012 10:45:11 GMT
Content-Length: 14
Expires: Thu, 31 Jan 2013 14:51:51 GMT
Cache-Control: max-age=31536000

ดังนั้นจึงส่ง a Cache-ControlและExpiresส่วนหัวที่ตั้งค่าเป็น 365 วันในอนาคต น่าเสียดายที่การรีเฟรชครั้งที่สองมันร้องขอวัตถุอีกครั้งด้วยIf-Modified-Sinceส่วนหัว

คำขอที่สอง

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
If-Modified-Since: Tue, 31 Jan 2012 10:45:11 GMT
Cache-Control: max-age=0

การตอบสนอง

HTTP/1.1 304 Not Modified
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:58:00 GMT
Vary: Accept-Encoding
Expires: Thu, 31 Jan 2013 14:58:00 GMT
Cache-Control: max-age=31536000

น่าเสียดายเนื่องจากซอฟต์แวร์พร็อกซีที่ล้าสมัยที่เราไม่สามารถใช้Keep-Aliveหรือวางเซิร์ฟเวอร์ / พร็อกซีอื่น ๆ ไว้หน้าแอปพลิเคชัน เรายังไม่สามารถปรับปรุงประสิทธิภาพของเซิร์ฟเวอร์และลดเวลาแฝงของเครือข่าย ฉันพยายามคิดว่าส่วนหัวที่เราสามารถส่งเพื่อกำจัดคำขอ 301 รายการได้อย่างไร ฉันได้ลองใช้ ETags แล้ว แต่ก็ไม่ได้สร้างความแตกต่างIf-modified-sinceเลย ฉันได้ลองลบLast-Modifiedส่วนหัวแล้ว แต่นั่นเป็นสาเหตุของคำขอ GET มาตรฐานโดยไม่มีการแคช (ตรวจสอบบันทึกเซิร์ฟเวอร์ยังคงได้รับคำขอ)

ลูกค้าคือการผสมผสานของ Firefox (ส่วนใหญ่), IE 7, 8 และ (บางคน) 9, Chrome และ Safari แต่พฤติกรรมนี้ดูเหมือนว่าจะปรากฏในการทดสอบเบราว์เซอร์ทั้งหมด

TL; DR;

เครือข่ายแย่มากฉันควรส่งส่วนหัวใดเพื่อบอกลูกค้าว่าไม่เคยส่งIf-modified-sinceคำขอไปยังเซิร์ฟเวอร์เพื่อตรวจสอบความถูกต้องของแคชและเก็บเนื้อหาไว้ในแคชจนกว่าExpiresจะพบส่วนหัว

ฉันอาจจะขาดอะไรบางอย่างที่ชัดเจน แต่ทุกอย่างที่ฉันพยายามดูเหมือนจะให้ผลลัพธ์ที่เหมือนกัน

เรามีเซิร์ฟเวอร์ NGINX อยู่หน้าเซิร์ฟเวอร์แอปพลิเคชันของเราเพื่อให้ฉันสามารถเพิ่ม / ลบส่วนหัวใด ๆ ตามที่ฉันต้องการ พร็อกซีของเราไม่สนับสนุน Keep-Alive และพวกเขาไม่มีทางที่จะปรับปรุงประสิทธิภาพเครือข่ายที่น่าเชื่อถือ เนื่องจากการออกแบบซอฟต์แวร์ที่น่ากลัวทำให้แอปพลิเคชันโหลดทรัพยากรมากกว่า 100 รายการต่อการโหลดหน้าเว็บแต่ละครั้ง (ใช่แล้วซอฟต์แวร์ระดับองค์กรแย่มาก) ด้วยความล่าช้าประมาณ 40-50ms ต่อวัตถุ


1
อืมมันแปลกนะ การส่งส่วนหัวการหมดอายุและอายุสูงสุดควรป้องกันการร้องขอภาพเพิ่มเติม แก้ไข: โดยวิธีการจัดการกับการส่ง JPG เป็นtext/plainอย่างไร
DisgruntledGoat

1
@DisgruntledGoat Ahh คุณได้ทำการสันนิษฐานว่าไฟล์. jpg นั้นเป็นภาพแทนที่จะเป็นเอกสารข้อความ ยินดีต้อนรับสู่โลกของฉัน =) (เป็นไฟล์ข้อความที่มี 'Hello World' สำหรับการทดสอบของฉันซอฟต์แวร์เพิ่งเปลี่ยนชื่อไฟล์ทั้งหมดตามลำดับ IMG_xxxx.jpg โดยไม่คำนึงถึงประเภท Cool huh?)
Smudge

คุณใช้อะไรเพื่อตั้งค่าส่วนหัวคำขอ http
barlop

คำตอบ:


25

คุณไม่สามารถควบคุมสิ่งที่ตัวแทนผู้ใช้ส่วนหัวตัดสินใจที่จะส่งถึงคุณ หากไฟล์ที่สงสัยนั้นอยู่ในแคชของเบราว์เซอร์และตัดสินใจว่าจะต้องตรวจสอบเวอร์ชันใหม่หรือไม่ ตามบทความนี้สิ่งเหล่านี้เป็นสถานการณ์ที่เบราว์เซอร์จะร้องขอโดยใช้ If-Modified-Since:

  • รายการที่แคชไม่มีวันหมดอายุและเนื้อหากำลังถูกเข้าถึงเป็นครั้งแรกในเซสชันของเบราว์เซอร์
  • รายการที่แคชมีวันที่หมดอายุ แต่หมดอายุแล้ว
  • ผู้ใช้ขออัปเดตหน้าเว็บโดยคลิกปุ่มรีเฟรชหรือกด F5

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

สิ่งหนึ่งที่ช่วยเหลืออาจจะเพิ่ม "สาธารณะ" Cache-Control: public, max-age=31536000ที่ส่วนหัวการควบคุมแคชคือ ฉันได้เรียนรู้เมื่อเร็ว ๆ นี้ว่าวันหมดอายุมากกว่าหนึ่งปีนั้นไม่ถูกต้อง เนื่องจากวันหมดอายุของคุณเป็นเวลาหนึ่งปีอย่างแน่นอนอาจลดขนาดลงภายในสองสามวันหรือหลายสัปดาห์เพื่อให้แน่ใจว่าไฟล์อยู่ในแคชของเบราว์เซอร์และจะไม่ถูกทิ้ง


น่าสนใจฉันจะลดวันหมดอายุลงเหลือ 60 วันและเพิ่มธงสาธารณะและดูว่าเกิดอะไรขึ้น สิ่งนี้ดูเหมือนว่าจะเกิดขึ้นกับการคลิกลิงค์แทนที่จะเป็น F5s (ตาม Firebug และบันทึกเซิร์ฟเวอร์)
Smudge

ในทางเทคนิคข้อมูลจำเพาะ HTTP / 1.1เพียงบอกว่า "เซิร์ฟเวอร์ไม่ควรส่งวันหมดอายุมากกว่าหนึ่งปีในอนาคต" (สันนิษฐานว่าเป็นเพราะเวลานานก่อนที่จะหมดอายุ) และ "ประมาณหนึ่งปี" ในอนาคตคือการหมดอายุที่เหมาะสม เวลาที่จะส่งเนื้อหาที่ไม่คาดว่าจะหมดอายุ
Ilmari Karonen

1
หลังจากเล่นไปเรื่อยๆ ฉันได้ข้อสรุปว่าการหมดอายุ 365d นั้นไม่ส่งผลกระทบต่อลูกค้าของเราแต่ฉันได้ทิ้งมันลงเพื่อความปลอดภัยดูเหมือนว่าCache-Control: public,...กุญแจนี้จะเป็นกุญแจสู่สถานการณ์ที่เฉพาะเจาะจงนี้
รอยเปื้อน

คุณหมายถึงส่วนหัว "สาธารณะ" ที่แก้ไขการเดินทางไปกลับที่ไม่จำเป็นหรือไม่? ฉันพยายามมัน แต่ไม่ประสบความสำเร็จ ...
phtrivier

2
ในกรณีที่ยังไม่ชัดเจนจากคำตอบของฉัน, โหลดหน้าเว็บในเบราว์เซอร์ของคุณจะขอไฟล์อีกครั้ง เพียงคลิกลิงก์เพื่อเปิดหน้าเว็บและเบราว์เซอร์จะใช้แคช
DisgruntledGoat


3

ฉันมีปัญหาเดียวกันและคำขอมีการกดปุ่มเซิร์ฟเวอร์เพื่อตอบสนองกับ304สถานะ - ฉันส่ง 304 ผ่านทาง C # และแน่นอนว่ามันจะกระทบกับเซิร์ฟเวอร์ ..

ฉันได้Cache-Control: privateตั้ง ไม่max-ageและไม่Expiresมันดำเนินการตามที่คาดไว้; ตีเซิร์ฟเวอร์ด้วยการIf-Modified-Sinceที่ผมทดสอบค่าเมื่อเทียบกับสิ่งที่ผมคาดหวังและส่งมอบ304w / ร่างกายตอบสนองว่างเปล่า - อื่น200และเต็มร่างกายตอบสนอง

การตั้งค่าExpiresส่วนหัวมีผลลัพธ์ที่ต้องการ200 - (from cache)บนไคลเอนต์ & ไม่มีการร้องขอ HTTP ที่ส่งถึงเซิร์ฟเวอร์

แต่ .. ผมพบว่าการตั้งค่าที่ทั้งสอง max-age=และExpiresสามารถทำให้เกิดการเบราว์เซอร์ที่จะไม่ส่งIf-Modified-Sinceส่วนหัวและไม่แคชที่ทุกคนถ้าค่าไม่ตรงกับ

สิ่งที่ควรระวังหากคุณมีปัญหาการแคช & ใช้ส่วนหัวร่วมกัน


1

ปิดหัวข้อเล็กน้อย แต่อาจมีประโยชน์ การปรับปรุงอีกครั้งสำหรับคำขอเนื้อหาที่แคชของคุณคือการแคชใน sessionStorage เพื่อให้คุณไม่จำเป็นต้องถามเซิร์ฟเวอร์เพื่อตรวจสอบแคชและรับ 304 ดูตัวอย่าง google เปิดคอนโซลและเขียน sessionStorage คุณจะเห็นว่าพวกเขากำลังแคช CSS หรือ DOM ด้วย sessionStorage แน่นอน, คุณไม่สามารถใช้ในเบราว์เซอร์ IE รุ่นเก่าได้


0

ดูซอร์สโค้ดของคุณและตรวจสอบให้แน่ใจว่าไม่มี META REFRESH เพื่อเปลี่ยนไปใช้หน้าอื่น ใช้สิ่งที่ต้องการ sendRedirect แทน ในการตั้งค่าของฉัน META REFRESH ผลิต 304s ใน IE แต่ไม่ใช่ Chrome sendRedirect ไม่ได้ผลิตสิ่งนี้ในเบราว์เซอร์อย่างใดอย่างหนึ่ง

<meta http-equiv="refresh" content="0;URL='nextpage'" />    

VS

<% response.sendRedirect("nextpage") %>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.