Nagłówki, aby zapobiec żądaniom 304 / If-Modified-since / HEAD

31

Jakie nagłówki mam wysłać, aby całkowicie zatrzymać wszystkie żądania na serwerze po buforowaniu treści?

Mamy serwer o bardzo dużych opóźnieniach (Sigh, VMWare), więc nawet wysłanie HEADżądania na serwer zajmuje + 40 ms.

Obecnie są to nagłówki wysyłane / odbierane;

Pierwsza prośba

Klient wysyła;

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

Serwer odpowiada;

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

Wysyła więc nagłówek Cache-Controli Expiresustawiony na 365 dni w przyszłości. Niestety przy drugim odświeżeniu żąda ponownie obiektu z If-Modified-Sincenagłówkiem.

Druga prośba

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

Odpowiedź;

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

Niestety z powodu głupiego, przestarzałego oprogramowania proxy, z którego nie możemy korzystać Keep-Aliveani umieszczać innych aplikacji / serwerów przed aplikacją. Nie możemy również poprawić wydajności serwera i zmniejszyć opóźnień sieci. Próbowałem dowiedzieć się, jakie nagłówki możemy wysłać, aby pozbyć się 301 żądań. Próbowałem użyć ETags, ale to nie robi różnicy, wciąż wysyła If-modified-sincenagłówek. Próbowałem również usunąć Last-Modifiednagłówek, ale powoduje to standardowe żądanie GET bez buforowania (sprawdzone dzienniki, serwer nadal otrzymuje żądania).

Klienci to mieszanka Firefox (głównie), IE 7, 8 i (niektóre) 9, Chrome i Safari, ale takie zachowanie wydaje się występować we wszystkich testowanych przeglądarkach.

TL; DR;

Okropna sieć, jakie nagłówki mam wysłać, aby powiedzieć klientom, aby nigdy nie wysyłali If-modified-sincedo serwera żądań w celu sprawdzenia ich pamięci podręcznej i przechowywania zawartości w pamięci podręcznej do momentu Expiresspełnienia nagłówka?

Prawdopodobnie brakuje mi czegoś oczywistego, ale wszystko, co próbuję, wydaje się przynosić takie same wyniki.

Serwer NGINX znajduje się przed naszym serwerem aplikacji, więc mogę dodawać / usuwać dowolne nagłówki według własnego uznania. Nasz serwer proxy nie obsługuje Keep-Alive i nie ma sposobu na poprawę wydajności sieci. Z powodu okropnego projektowania oprogramowania aplikacja internetowa ładuje +100 zasobów przy każdym ładowaniu strony (tak, oprogramowanie korporacyjne jest do bani) z opóźnieniem ~ 40-50ms na obiekt.

Plama
źródło
1
Hmm, to dziwne. Wysyłanie nagłówków wygasających i maksymalnego wieku powinno zapobiec dalszym żądaniom obrazu. Edycja: a propos, jaki jest układ wysyłania JPG jako text/plain?
DisgruntledGoat
1
@DisgruntledGoat Ahh, założyłeś, że plik .jpg to tak naprawdę obraz, a nie dokument tekstowy. Witaj w moim świecie =) (Jest to rzeczywiście to plik tekstowy, który zawiera „Hello World” dla moich testów, oprogramowanie po prostu zmienia nazwy wszystkich plików kolejno IMG_xxxx.jpg niezależnie od typu Chłodny huh).?
rozmazywanie
Czego używałeś do ustawiania nagłówków żądania HTTP?
barlop

Odpowiedzi:

25

Naprawdę nie możesz kontrolować, które nagłówki agenty użytkownika zdecydują się wysłać do Ciebie. Jeśli dany plik znajduje się w pamięci podręcznej przeglądarki i zdecyduje, że musi sprawdzić, czy jest nowa wersja, zrobi to. Zgodnie z tym artykułem są to sytuacje, w których przeglądarki zażądają użycia If-Modified-Since:

  • Wpis w pamięci podręcznej nie ma daty ważności, a treść jest otwierana po raz pierwszy w sesji przeglądarki
  • Wpis w pamięci podręcznej ma datę ważności, ale wygasł
  • Użytkownik zażądał aktualizacji strony, klikając przycisk Odśwież lub naciskając F5

Jeśli więc ponownie ładujesz stronę w celu przetestowania pamięci podręcznej, nie będzie działać, ponieważ przeglądarka ponownie zażąda obrazów. Spróbuj kliknąć link, a następnie kolejny link z powrotem do pierwszej strony. Jeśli użytkownicy regularnie przeładowują strony, może być konieczne ponowne przemyślenie struktury witryny / aplikacji, aby temu zapobiec.

Jedną z rzeczy, które mogą pomóc, jest dodanie „public” do nagłówka kontroli pamięci podręcznej, tj Cache-Control: public, max-age=31536000. Niedawno dowiedziałem się również, że termin ważności przekraczający jeden rok jest nieważny. Ponieważ data wygaśnięcia wynosi dokładnie rok, być może skrócenie tego o kilka dni lub tygodni zapewni, że plik pozostanie w pamięci podręcznej przeglądarki i nie zostanie odrzucony.

DisgruntledGoat
źródło
Co ciekawe, obniżę okres ważności do 60 dni, dodam flagę publiczną i zobaczę, co się stanie. To wydawało się dzieje na łącza kliknięć zamiast F5 (zgodnie z Firebug i logów serwera)
Smudge
Technicznie rzecz biorąc, specyfikacja HTTP / 1.1 mówi tylko, że „serwery NIE POWINNY wysyłać dat wygaśnięcia więcej niż rok w przyszłości” (prawdopodobnie dlatego, że jest to absurdalnie długi czas przed datą wygaśnięcia) i że „około jeden rok w przyszłości jest odpowiednim terminem ważności czas na przesłanie treści, które nigdy nie wygasną.
Ilmari Karonen
1
Po krótkiej zabawie doszedłem do wniosku, że wygaśnięcie 365d nie ma wpływu na naszych klientów, ale zrzuciłem je dla bezpieczeństwa, wydaje się, że Cache-Control: public,...było to kluczem do tej konkretnej sytuacji.
Smudge
Czy masz na myśli, że nagłówek „public” naprawiał niepotrzebne podróże w obie strony? Próbowałem, ale bezskutecznie ...
phtrivier
2
W przypadku, gdy nie jest to jasne z mojej odpowiedzi, przeładowanie strony w przeglądarce poprosi o pliki ponownie . Wystarczy kliknąć linki, aby otworzyć strony, a przeglądarka korzysta z pamięci podręcznej.
DisgruntledGoat
3

Miałem ten sam problem, a żądania zdecydowanie uderzają w serwer, aby mógł odpowiedzieć ze 304statusem - wysyłam 304 przez jakiś C # i na pewno trafi na serwer ..

Tylko Cache-Control: privateustawiłem. Nie max-agei nie ExpiresDziałało zgodnie z oczekiwaniami; If-Modified-Sincetrafiłem na serwer z miejscem, w którym testuję wartość w porównaniu z tym, czego oczekuję i dostarczam 304w / pustą treść odpowiedzi - w przeciwnym razie 200i wypełnij treść odpowiedzi.

Ustawienie Expiresnagłówka przyniosło pożądane wyniki, 200 - (from cache)na kliencie i żadne żądania HTTP nie trafiły na serwer.

Ale .. Odkryłem, że ustawienie ZARÓWNO max-age= i Expiresmoże powodować, że przeglądarki nie wysyłają If-Modified-Sincenagłówka ORAZ nie buforują wcale, jeśli wartości się nie zgadzają .

Należy pamiętać, jeśli masz problemy z buforowaniem i używasz różnych nagłówków w połączeniu.

Andrew Scott
źródło
1

Trochę nie na temat, ale może pomocny. Kolejnym ulepszeniem twoich żądań zawartości pamięci podręcznej jest buforowanie w sessionStorage, abyś nie musiał prosić serwera o sprawdzenie pamięci podręcznej i otrzymanie 304. Poszukaj na przykład google, otwórz konsolę i napisz sessionStorage. Zobaczysz, że buforują CSS lub DOM za pomocą sessionStorage. ofc, nie możesz używać tego w starych przeglądarkach IE.

Pablo Estornut
źródło
0

Przejrzyj kod źródłowy i upewnij się, że nie ma META REFRESH, aby przejść na inną stronę. Zamiast tego użyj czegoś takiego jak sendRedirect. Przy moim ustawieniu META REFRESH produkuje 304 w IE, ale nie Chrome. sendRedirect nie wytwarza tego w żadnej przeglądarce.

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

vs

<% response.sendRedirect("nextpage") %>
Richard Sandoz
źródło