Wczytywanie stron z pamięci podręcznej: kiedy ETag i Last-Modified ograniczają pobieranie

Management Summary
Przeglądarka może zachować kopię treści witryny, aby nie pobierać tych samych danych ponownie. Gdy kopia wymaga sprawdzenia, oznaczenie wersji lub data zmiany pozwala serwerowi potwierdzić jej aktualność. Ogranicza to powtórne przesyłanie niezmienionej zawartości, choć samo pytanie nadal zajmuje czas. Artykuł wyjaśnia różnicę między użyciem zapisanej kopii, jej sprawdzeniem i pobraniem nowej. Pomaga to ocenić, czy pamięć podręczna strony rzeczywiście zmniejsza zbędną pracę.
Spis treści
Zapisana odpowiedź jest świeża, dopóki reguły pamięci podręcznej pozwalają używać jej bez ponownego pytania serwera. Pozwala to uniknąć żądania sieciowego. Gdy potrzebne jest sprawdzenie, walidator może zapobiec ponownemu przesłaniu treści: pasujące warunkowe żądanie GET może otrzymać 304 Not Modified. Żądanie i przetwarzanie nadal kosztują czas. Pamięć bez walidatorów pozostaje więc przydatna, dopóki zapisana odpowiedź nadaje się do ponownego użycia.
Historyczny przebieg z 5 września 2026 r. obejmował dwadzieścia adresów początkowych. Jedenaście zapisanych odpowiedzi nie zawierało ani ETagu, ani Last-Modified. Opis dotyczy tamtych odpowiedzi, a nie zasadniczej niezdolności jedenastu całych witryn do obsługi żądań warunkowych.

Dwa walidatory, różne gwarancje
Last-Modified opisuje czas ostatniej modyfikacji z dokładnością do sekundy. Odpowiadające pole żądania to If-Modified-Since. Kilka zmian w jednej sekundzie może przekroczyć tę rozdzielczość.
ETag to oznaczenie wersji, którego treści klient nie musi interpretować. Oznaczenie jest odsyłane w If-None-Match. Wiarygodność zależy od sposobu tworzenia: skrót treści lub inny odpowiedni mechanizm wersjonowania może rozróżniać zmiany niewidoczne w znaczniku czasu. ETag nie musi być skrótem treści.
Silny ETag oznacza identyczne dane reprezentacji. Słaby ETag, na przykład W/"abc", dopuszcza dane równoważne bez identyczności bajtowej. Dynamiczne tworzenie strony nie wymaga automatycznie słabego tagu; znaczenie ma rzeczywista gwarancja porównania.
Co zawiera zapisana próba
Archiwum zawiera pięć ETagów, w tym trzy słabe, oraz pięć pól Last-Modified. Jedna odpowiedź ma oba pola, jedenaście nie ma żadnego. Sześć odpowiedzi podaje no-store, ale tylko cztery z tych sześciu nie mają walidatorów. Siedem odpowiedzi nie zawiera zatem walidatorów bez jednoczesnego no-store. Nie dowodzi to jeszcze możliwości przechowywania: znaczenie mają również status, inne dyrektywy i rodzaj pamięci.
Dwa wyniki mają oznaczenie błędu HTTP, w tym jeden z dwóch bez Cache-Control. Zapisane podsumowanie nie zachowuje dokładnych kodów tych odpowiedzi. Próba nie obejmuje więc dwudziestu potwierdzonych poprawnych odpowiedzi stron głównych i nie stanowi reprezentatywnej statystyki rynku.
Analizator przypisał sześć zakazów przechowywania, cztery natychmiastowe ponowne pobrania, trzy stałe rewalidacje, cztery przypadki świeżości z późniejszą rewalidacją, jeden ze świeżością i ponownym pobraniem oraz dwie klasy heurystyczne. To klasyfikacja nagłówków, a nie zaobserwowane historie przeglądarek. Na przykład 54 sekundy były wartością max-age, nie dowodem dokładnie tak długiego przechowywania w każdej przeglądarce.
Świeżość i walidacja to odrębne kwestie
no-store zabrania przechowywania w pamięci HTTP; no-cache wymaga udanej walidacji przed ponownym użyciem. max-age=0 sprawia, że odpowiedź natychmiast staje się nieświeża. Pamięć prywatna i współdzielona mogą podlegać różnym zasadom, zwłaszcza przy private lub s-maxage.
Bez wyraźnie podanego okresu ponownego użycia pamięć podręczna może w określonych warunkach sama oszacować ten okres. To buforowanie heurystyczne. Dziesięć procent odstępu od Last-Modified to przykład, a nie obowiązkowy czas życia. Żadna z dwóch badanych odpowiedzi bez Cache-Control nie zawierała Last-Modified, więc archiwum nie potwierdza takiego obliczenia dla tych odpowiedzi. Test HTTP nie ustala również działania przycisków wstecz i dalej.
Kompresja i pułapka ETagu
Dokumentacja Apache wskazuje, że domyślne zachowanie AddSuffix modułów kompresji może uniemożliwiać odpowiedzi 304 dla skompresowanych danych. Warunkowy test tego samego wariantu jest więc przydatny. Sam powtórzony status 200 nie dowodzi błędu: wybrana reprezentacja mogła rzeczywiście ulec zmianie.
DeflateAlterETag NoChange i BrotliAlterETag NoChange zachowują pierwotny tag, ale Apache wyraźnie opisuje wynikające ograniczenie rozróżniania wariantów. Wspólny silny tag dla bajtów skompresowanych i nieskompresowanych nie staje się poprawny dzięki Vary: Accept-Encoding. Vary steruje wyborem wpisu w pamięci; silne walidatory dotyczą identyczności danych reprezentacji.
Właściwe rozwiązanie zależy od serwera i przetwarzania w pamięci podręcznej: poprawne odrębne silne tagi, prawidłowo obsługiwane słabe tagi dla równoważnych reprezentacji albo usunięcie nieodpowiedniego ETagu kosztem tej możliwości walidacji. Żądania zakresowe i odpowiedzi warunkowe wymagają sprawdzenia. Pojedyncze 200 nie uzasadnia uniwersalnej dyrektywy produkcyjnej. Usunięto więc wcześniejsze bezwarunkowe zapewnienie o bezpieczeństwie NoChange.

Powtarzalny warunkowy GET
Przykład Bash wymaga curl 7.68.0 lub nowszego. Zachowuje ten sam URL i preferencję kodowania oraz zapisuje otrzymany ETag bez zmian. Skrypt kończy działanie, jeśli pierwsza odpowiedź nie ma statusu 200 lub nie zawiera tagu. URL jest zastępczy; przy przekierowaniach właściwy adres docelowy wymaga osobnego wyboru i testu.
#!/usr/bin/env bash
set -euo pipefail
url='https://example.com/style.css'
tag_file=$(mktemp)
trap 'rm -f "$tag_file"' EXIT
status=$(curl --silent --show-error --max-time 20 \
-H 'Accept-Encoding: gzip' --etag-save "$tag_file" \
--output /dev/null --write-out '%{http_code}' "$url")
[[ "$status" == 200 ]] || { printf 'Initial HTTP status: %s\n' "$status" >&2; exit 1; }
[[ -s "$tag_file" ]] || { printf 'No ETag received\n' >&2; exit 1; }
curl --silent --show-error --max-time 20 \
-H 'Accept-Encoding: gzip' --etag-compare "$tag_file" \
--output /dev/null --dump-header - --write-out '\nHTTP %{http_code}\n' "$url"Wyświetlone nagłówki odpowiedzi pokazują drugi ETag i kodowanie. Odpowiedź 304 nie ma treści; przy 200 potrzebne jest sprawdzenie wariantu, zmiany i zachowania serwera. Błędy sieci i inne statusy pozostają odrębnymi wynikami. Identyczne Accept-Encoding kontroluje jedną daną wejściową, lecz nie dowodzi identycznej wybranej kompresji ani treści.
Analizator Cache-Control i rewalidacji wysyła otrzymany ETag i datę w osobnych testach. Nie bada wspólnego pierwszeństwa warunków ani pełnej pamięci przeglądarki. Licznik bajtów mierzy zdekodowaną treść do 256 KiB, a nie cały skompresowany ruch sieciowy. Ostrzeżenie obejmuje też zmieniony ETag z odpowiedzią 200, choć takie zachowanie może być poprawne. Czas heurystyczny i klasy wymagają zatem interpretacji.
Pytania i odpowiedzi
Co obowiązuje przy obu warunkach w żądaniu?
If-None-Match ma pierwszeństwo; przy obecności tego pola If-Modified-Since zostaje pominięte. Pasująca data nie zastępuje więc niepasującego ETagu. Znaczenie ma rzeczywiste żądanie klienta; nie każda przeglądarka zawsze odsyła oba pola przy każdej wizycie.
Czy słaby ETag wystarczy do 304?
Tak. If-None-Match stosuje porównanie słabe: W/"abc" i "abc" pasują. Nie czyni to słabego tagu odpowiednim do testu If-Range z tagiem encji ani do silnego porównania If-Match.
Czy każde 200 dowodzi usterki?
Nie. Zmieniona reprezentacja zwykle wymaga nowej treści. Diagnoza obejmuje żądanie, wybrany wariant i zwrócony walidator. Widok sieciowy przeglądarki, logi serwera oraz testy automatyczne również mogą ujawnić problem; curl jest kolejną metodą.
Czy 304 oszczędza obiegu sieciowego?
Nie. Walidacja przez sieć nadal wymaga odpowiedzi, być może z pośredniej pamięci zamiast serwera źródłowego. Świeży wpis nadający się do użycia może całkowicie oszczędzić żądania. Wersjonowane pliki statyczne mogą mieć dłuższą świeżość, jeżeli każda zmiana treści oznacza nowy URL.


