Dlaczego Apache wysyła 200 OK, podczas gdy dopasowania Ostatnia modyfikacja Jeśli zmodyfikowano od tego czasu?

10

Próbuję zachować podstawowe zachowanie dotyczące mojej strategii buforowania: pliki powinny być buforowane i każdorazowo ponownie sprawdzane na serwerze. Chciałbym więc, aby Apache odesłał 304.

Oto okno dialogowe, które pojawia się przy każdym odświeżeniu przeglądarki:

Status Code:200 OK

Request Headers

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie: ...
Host:...
If-Modified-Since:Tue, 14 Oct 2014 15:10:37 GMT
If-None-Match:"1461-505636af08fcd-gzip"
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36

Response Headers

Accept-Ranges:bytes
Cache-Control:No-cache
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:1412
Content-Type:text/html
Date:Tue, 14 Oct 2014 16:58:05 GMT
ETag:"1461-505636af08fcd-gzip"
Keep-Alive:timeout=5, max=99
Last-Modified:Tue, 14 Oct 2014 15:10:37 GMT
Server:Apache/2.4.6 (Ubuntu)
Vary:Accept-Encoding

(pochodzi z devtools chrome, bez zaznaczonej opcji Wyłącz pamięć podręczną)

Widać, że odpowiedź zawiera nagłówek Cache-Control: No-cache Header oraz że nagłówek If-Modified-Since pasuje do ostatniej modyfikacji. ETag również pasuje.

Czy w takim przypadku Apache nie powinien wysłać 304?

EDYTOWAĆ

Wyłączanie ETagów w apache za pomocą

 Header  unset ETag

sprawia, że ​​zachowanie buforowania jest bardziej przewidywalne ...

zrz
źródło
Myślę, że Cache-Control:max-age=0wyłączyłem pamięć podręczną, więc widzisz Cache-Control:No-cacheodpowiedź.
ThoriumBR
Jawnie ustawiłem Cache-Control: No-cache w mojej konfiguracji apache, ponieważ z w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1 rozumiem, że powoduje to przedłużenie ważności każdego żądania. Czy ponowna walidacja oznacza ponowne wysłanie pliku? Powiedziałbym, że powinien użyć If-modyfikacji-od, aby ustalić, czy jest to 200, czy 304.
zrz

Odpowiedzi:

8

To wydaje się być starym błędem , wyjaśniającym, dlaczego Header unset ETagrobi różnicę.

Apache 2.4.0+ automatycznie dołącza nazwę metody kompresji do ETag (jak widać w nagłówkach) i zapobiega odpowiedzi 304.

Najnowsze wersje mod_deflate obsługują DeflateAlterETag, którego można użyć do kontrolowania tego zachowania:

DeflateAlterETag NoChange
Mathias R. Jessen
źródło
3
Jest to poprawne, ale Apache 2.4 nie zawiera tej opcji, tylko Apache 2.5. Jednak osobiście nie uważam znaczników ETag za użyteczne, ponieważ Apache opiera je na dacie ostatniej modyfikacji, a nie na zawartości pliku. Tak więc wyłączenie ETagów wraca do nagłówka If-Modified-Since, który i tak jest oparty na dacie ostatniej modyfikacji. Możesz zmienić ETag w Apache, aby był oparty na rozmiarze, ostatnio zmodyfikowany i / lub i-węzeł - z domyślnym rozmiarem i ostatnią modyfikacją - ale dopóki nie dodadzą opcji obliczania ETag na podstawie sumy kontrolnej zawartości pliku, jego ograniczone zastosowanie IMHO. Więc je wyłączam.
Barry Pollard,
1
@BazzaDP To ma sens. 2.5 ma również taką DeflateAlterETag Removeopcję
Mathias R. Jessen,
0

Ten wyróżnia się w żądaniu jako nieco dziwny:

Cache-Control:max-age=0

Prawdopodobnie ważniejsze jest jednak to, że zwracana zawartość to html. Czy jest generowany dynamicznie? Apache MOŻE wysłać odpowiedź 304, ale jeśli nie podajesz treści statycznych, wykonywanie tego połączenia nie jest zadaniem Apache i sprowadza się to do logiki aplikacji. Np. Większość aplikacji php ma ograniczone wsparcie dla takich rzeczy.

Pomocna może być pamięć podręczna frontonu, ponieważ aplikacja buforująca może sprawdzić czas modyfikacji, etag itp., Ale tylko wtedy, gdy zarówno aplikacja, jak i nagłówki żądania są przyjazne dla pamięci podręcznej. Na przykład aplikacja musi ustawić odpowiednie nagłówki, aby wskazać, że zawartość jest buforowalna, a takie elementy, jak nagłówek kontroli pamięci podręcznej w żądaniu, spowodują zanegowanie pamięci podręcznej. Twoje nagłówki nie wyglądają na przyjazne dla pamięci podręcznej.

Mc0e
źródło
Żądany plik jest statycznym plikiem HTML, dla którego Apache ma odpowiedni czas modyfikacji. (Ostatnia modyfikacja: wt., 14 października 2014 15:10:37 GMT). nagłówek max-age = 0 znajduje się w żądaniu wysłanym przez chrome, gdy wpisuję adres URL i naciśnij Enter. Czy to z powodu wcześniejszych odpowiedzi?
zrz
Czytam, że Chrome automatycznie dodaje Cache-Control: max-age = 0 do żądania (z wyjątkiem pierwszego załadowania Chrome, wpisz adres URL, naciśnij Enter). Ale nie wydaje się, aby miało to wpływ na inne serwery (sieci CDN wysyłają 304, nawet przy maksymalnym wieku = 0 w żądaniu).
zrz
@zrz: ograniczenie buforowania pośredników jest bardzo przydatne podczas debugowania, ale w przeciwnym razie wpłynęłoby negatywnie na wydajność. Sprawdź kontekst tego, co czytasz na temat tego, co robi chrom. Pod względem tego, co robi Apache, jest dość konfigurowalny. Kontrola pamięci podręcznej jest instrukcją dla pośrednich pamięci podręcznych, a nie dla serwera źródłowego. Apache może jednak działać jako pamięć podręczna pośrednicząca i może być skonfigurowany do wykonywania różnego rodzaju czynności. Myślę, że jeśli wyciągniesz instrukcje dotyczące buforowania, uzyskasz zachowanie bardziej podobne do tego, czego oczekujesz od serwera źródłowego.
mc0e
0

Jeśli masz skonfigurowanego Apache Cache-Control:No-cache, Apache nigdy nie wyśle HTTP 304 Not modifieddo klienta.

Jeśli chcesz ponownie zweryfikować niektóre żądania, umieść je Cache-Control:No-cachetylko na stronach, na których jest to potrzebne. Nie musisz ponownie sprawdzać poprawności wszystkich zasobów i marnujesz w ten sposób przepustowość.

ThoriumBR
źródło
Wydaje mi się, że myli mnie termin „rewalidacja”. Dla mnie oznacza to sprawdzenie, czy to 304. Czy się mylę?
zrz
Mylisz się. Unieważnij, aby ponownie wysłać dane do klienta i zmusić go do ponownego przeczytania wszystkiego, nawet jeśli już zawiera te same informacje. Zasadniczo wyłączasz pamięć podręczną na każdym kliencie.
ThoriumBR
To wiele wyjaśnia. Ostatnią rzeczą, którą muszę wyjaśnić, mając to na uwadze, jest to, że Apache wysyła 304 dla niektórych zasobów (na przykład png), podczas gdy nadal mam ten zestaw Kontroli pamięci podręcznej, który nie ustawił żadnej pamięci podręcznej w odpowiedzi i do maksymalnego wieku = 0 w żądaniu. Jakieś wskazówki?
zrz
@ThoriumBR Jeśli poprawnie cię zinterpretowałem, obie odpowiedzi są tutaj niepoprawne; no-cache (w przeciwieństwie do no-store) nie oznacza „nie buforuj” i może skutkować 304, jeśli zawartość się nie zmieniła. Rzeczywiście OP oczekiwał tego, ale nie dostał go z powodu problemu z etagiem. must-revalidate odnosi się do sposobu obsługi nieaktualnych treści i nie zawsze wysyła „dane od nowa”.
Nick