Header untuk mencegah permintaan 304 / If-modified-since / HEAD

31

Header apa yang harus saya kirim untuk langsung menghentikan semua permintaan ke server setelah konten di-cache?

Kami memiliki server latensi yang sangat tinggi (Sigh, VMWare) sehingga bahkan mengirim HEADpermintaan ke server membutuhkan + 40ms.

Saat ini adalah tajuk yang dikirim / diterima;

Permintaan pertama

Klien mengirim;

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

Server merespons;

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

Jadi ia mengirim Cache-Controldan Expiresmengatur header ke 365 hari di masa depan. Sayangnya pada refresh kedua ia meminta objek lagi dengan If-Modified-Sinceheader.

Permintaan kedua

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

Tanggapan;

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

Sayangnya karena perangkat lunak proxy usang konyol yang tidak dapat kita gunakan Keep-Alive, atau letakkan server / proksi lain di depan aplikasi. Kami juga tidak dapat meningkatkan kinerja server dan mengurangi latensi jaringan. Saya sudah mencoba mencari tahu header apa yang bisa kami kirim untuk menyingkirkan 301 permintaan. Saya sudah mencoba menggunakan ETags tetapi tidak ada bedanya, masih mengirimkan If-modified-sinceheader. Saya juga mencoba menghapus Last-Modifiedtajuk tetapi itu hanya menyebabkan permintaan GET standar tanpa caching (Memeriksa log, server masih menerima permintaan).

Klien adalah campuran dari Firefox (sebagian besar), IE 7, 8 dan (beberapa) 9, Chrome dan Safari tetapi perilaku ini tampaknya muncul di semua browser yang diuji.

TL; DR;

Jaringan yang mengerikan, tajuk apa yang harus saya kirim untuk memberi tahu klien agar tidak pernah mengirim If-modified-sincepermintaan ke server untuk memvalidasi cache mereka, dan menyimpan konten di-cache hingga Expiresheader terpenuhi?

Saya mungkin kehilangan sesuatu yang jelas tetapi semua yang saya coba tampaknya menghasilkan hasil yang sama.

Kami memiliki server NGINX di depan server aplikasi kami sehingga saya dapat menambah / menghapus header apa pun sesuka saya. Proksi kami tidak mendukung Keep-Alive dan tidak ada cara untuk meningkatkan kinerja jaringan yang keras. Karena desain perangkat lunak yang mengerikan aplikasi web memuat 100 sumber daya pada setiap pemuatan halaman (Ya, perangkat lunak perusahaan menyebalkan) dengan latensi ~ 40-50ms per objek.

Noda
sumber
1
Hmm, itu aneh. Mengirim Header yang Kadaluwarsa dan usia maks harus mencegah permintaan gambar lebih lanjut. Sunting: omong-omong, bagaimana dengan mengirim JPG text/plain?
DisgruntledGoat
1
@DisgruntledGoat Ahh, Anda membuat anggapan bahwa file .jpg sebenarnya adalah gambar daripada dokumen teks. Selamat datang di duniaku =) (Ini sebenarnya file teks yang berisi 'Hello World' untuk pengujian saya, perangkat lunak hanya mengganti nama semua file secara berurutan IMG_xxxx.jpg terlepas dari jenisnya. Keren ya?)
Smudge
apa yang Anda gunakan untuk mengatur header permintaan http?
barlop

Jawaban:

25

Anda tidak dapat benar-benar mengendalikan apa yang ditentukan oleh header yang dikirim oleh agen pengguna kepada Anda. Jika file tersebut dalam cache browser dan memutuskan perlu memeriksa versi baru maka itu akan. Menurut artikel ini , ini adalah situasi yang akan diminta browser menggunakan Jika-Dimodifikasi-Sejak:

  • Entri yang di-cache tidak memiliki tanggal kedaluwarsa dan konten sedang diakses untuk pertama kalinya dalam sesi browser
  • Entri yang di-cache memiliki tanggal kedaluwarsa tetapi telah kedaluwarsa
  • Pengguna telah meminta pembaruan halaman dengan mengklik tombol Refresh atau menekan F5

Jadi, jika Anda memuat ulang halaman untuk menguji cache Anda, itu tidak akan berfungsi karena browser akan meminta kembali gambar. Coba klik tautan lalu tautan lain kembali ke halaman pertama. Jika pengguna Anda secara teratur memuat ulang halaman, maka Anda mungkin perlu memikirkan kembali struktur situs / aplikasi Anda untuk mencegahnya.

Satu hal yang dapat membantu adalah menambahkan "publik" ke header kontrol cache, yaitu Cache-Control: public, max-age=31536000. Saya juga baru tahu bahwa tanggal kedaluwarsa lebih dari satu tahun tidak valid. Karena tanggal kedaluwarsa Anda tepat satu tahun, mungkin dengan menurunkannya beberapa hari atau minggu akan memastikan file tetap tersimpan dalam cache browser dan tidak dibuang.

DisgruntledGoat
sumber
Menarik, saya akan menurunkan kedaluwarsa menjadi 60 hari dan menambahkan bendera publik, dan melihat apa yang terjadi. Ini tampaknya terjadi pada klik tautan daripada F5 (menurut Firebug dan log server)
Smudge
Secara teknis, HTTP / 1.1 spec hanya mengatakan bahwa "server TIDAK HARUS mengirim tanggal Kedaluwarsa lebih dari satu tahun di masa depan" (mungkin karena itu waktu yang sangat lama sebelum kedaluwarsa) dan bahwa "kira-kira satu tahun" di masa depan adalah kedaluwarsa yang sesuai waktu untuk mengirim konten yang tidak pernah kedaluwarsa.
Ilmari Karonen
1
Setelah sedikit bermain-main, saya menyimpulkan bahwa kadaluwarsa 365d tidak mempengaruhi klien kami, tetapi saya telah menjatuhkannya agar aman, sepertinya itu Cache-Control: public,...adalah kunci untuk situasi khusus ini.
Smudge
Apakah maksud Anda tajuk "publik" memperbaiki bolak-balik yang tidak perlu? Saya mencobanya, tetapi tidak berhasil ...
phtrivier
2
Jika tidak jelas dari jawaban saya, memuat ulang halaman di browser Anda akan meminta file lagi . Cukup klik tautan untuk membuka halaman dan browser menggunakan cache-nya.
DisgruntledGoat
3

Saya memiliki masalah yang sama, dan Permintaan pasti mengenai server untuk menanggapi dengan 304status - Saya mengirim 304 melalui beberapa C # dan pasti hits server ..

Saya hanya Cache-Control: privatemengatur. Tidak max-agedan tidak ExpiresIni beroperasi seperti yang diharapkan; tekan server dengan If-Modified-Sincetempat saya menguji nilainya dibandingkan dengan apa yang saya harapkan dan kirimkan dengan 304respons kosong - yang lain 200& isi tanggapan penuh.

Pengaturan Expiresheader memiliki hasil yang diinginkan, 200 - (from cache)pada klien & tidak ada permintaan HTTP mengenai server.

Tapi .. Saya menemukan bahwa pengaturan KEDUA max-age= & Expiresdapat menyebabkan browser tidak mengirim If-Modified-Sinceheader DAN tidak melakukan cache sama sekali jika nilainya tidak cocok .

Sesuatu yang perlu diperhatikan jika Anda memiliki masalah caching & menggunakan header berbeda dalam kombinasi.

Andrew Scott
sumber
1

Sedikit di luar topik tapi mungkin bermanfaat. Peningkatan lain untuk permintaan konten yang di-cache Anda, adalah untuk cache di sessionStorage sehingga Anda tidak perlu meminta server untuk memvalidasi cache dan menerima 304. Cari misalnya google, buka konsol dan tulis sessionStorage. Anda akan melihat bahwa mereka melakukan caching CSS atau DOM dengan sessionStorage. ofc, Anda tidak dapat menggunakannya di browser IE lama.

Pablo Estornut
sumber
0

Lihatlah kode sumber Anda dan pastikan tidak ada META REFRESH untuk beralih ke halaman lain. Gunakan sesuatu seperti sendRedirect sebagai gantinya. Pada pengaturan saya META REFRESH menghasilkan 304 di IE, tetapi tidak Chrome. sendRedirect tidak menghasilkan ini di kedua browser.

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

vs.

<% response.sendRedirect("nextpage") %>
Richard Sandoz
sumber