W notce tej przyjrzymy się dość kłopotliwemu nagłówkowi HTTP, jakim jest ETag.
Mówiąc pokrótce, nagłówek ETag odpowiada za buforowanie obiektów (dokumentów, plików) po stronie klienta – informuje klienta (przeglądarkę, inny czytnik) o tym, czy przechowywany przez wewnętrzny system buforowania obiekt jest nadal aktualny.
W niniejszym wpisie opiszę sposoby definiowania tego nagłówka, jego główne zalety, a także wady, które zniechęcają mnie do jego wykorzystywania w swoich projektach.
Zgodnie z domyślnymi ustawieniami serwera Apache, wysyła on w odpowiedzi HTTP dwa nagłówki odpowiadające za buforowanie danych po stronie klienta.
Last-Modified
Informuje przeglądarkę o tym, kiedy nastąpiła ostatnia modyfikacja żądanego pliku.
Jeśli data ostatniej modyfikacji pliku pobieranego z serwera jest późniejsza niż data ostatniej modyfikacji obiektu przechowywanego po stronie przeglądarki – wtedy klient wie, iż plik należy ponownie pobrać do buforu i wyświetlić w przeglądarce.
Wszystko to dzieje się automatycznie we wszystkich nowoczesnych przeglądarkach (o ile użytkownik nie zablokował tej opcji).
ETag
Klient odwiedza wiele stron, czasem wielokrotnie ten sam adres. Przeglądarka w tym czasie tworzy bufor (zapisuje pliki na dysku na jakiś czas w celu szybszego wczytania całości strony w przypadku ponownych odwiedzin).
No więc nagłówek ten mówi przeglądarce, czy od ostatnich odwiedzin pożądany obiekt uległ jakimś modyfikacjom – czy przechowywany w buforze plik jest nadal aktualny. Zwracana przez nagłówek wartość wygląda mniej więcej następująco:
1 | ETag: "686897696a7c876b7e" |
Skąd serwerowi wiadomo, kiedy dokonano ostatniej modyfikacji pliku? Mamy do dyspozycji kilka opcji poinstruowania serwera na podstawie czego ma decydować o „świeżości” pliku w buforze:
- Size – sprawdzenie czy rozmiar pliku się zgadza,
- MTime – czas ostatniej modyfikacji pliku,
- INode –suma kontrolna pliku (węzeł) – pobierany jest skrót MD5 z zawartości pliku, który mówi o tym, czy zawartość tego pliku uległa jakimkolwiek zmianom
Przykładowo, możemy przykazać serwerowi (Apache), by ustawiał nagłówek ETag w następujący sposób:
1 | FileETag MTime Size |
oznacza to, iż sprawdzanie aktualności pliku odbędzie się na podstawie czasu ostatniej aktualizacji oraz wielkości pliku.
Dyrektywę FileETag należy wstawić w pliku konfiguracyjnym serwera Apache. Możliwe jest także dodanie tej dyrektywy do plików .htaccess na poziomie konkretnych plików (np. tylko z treścią statyczną).
Aby ustawić najwyższy poziom sprawdzania aktualności pliku można wprowadzić taką linijkę do ustawień swojego serwera:
1 | FileETag INode MTime Size |
lub
1 | FileETag All |
Spowoduje to oczywiście dłuższy czas takiego sprawdzania aktualności pliku w buforze, co przełoży się także na dłuższe wczytywanie się tej strony.
Jeśli natomiast chcemy całkowicie wyłączyć ten nagłówek musimy wprowadzić następującą dyrektywę:
1 | FileETag None |
Spowoduje to, że w odpowiedzi HTTP serwera nagłówek ETag będzie całkowicie pomijany. Ma to jedną podstawową zaletę: nagłówek ETag wprowadza czasem zamęt i nieporozumienia.
Kiedy nagłówek ETag może zaszkodzić?
Niewłaściwe skonfigurowanie tego nagłówka może wprowadzić spory zamęt. Przykładowo, wprowadzimy poniższą dyrektywę do ustawień serwera Apache:
1 | FileETag Size |
Oznacza to, że serwer będzie uwzględniał jedynie rozmiar pliku, nie weźmie niczego innego przy uzgadnianiu aktualności pliku w buforze.
Następnie możesz zmienić obrazek, lecz rozmiar pozostanie taki sam. W buforze klienta będzie teraz nieaktualny obrazek lub inny dokument. To jest niepożądana sytuacja i nigdy nie powinno się do tego dopuszczać.
Również ustawienie nagłówka ETag w innej postaci nie gwarantuje, iż zostanie zachowana aktualność pliku w buforze.
Słowem podsumowania…
Niektórzy programiści decydują się więc na wyłączenie tego nagłówka, a zamiast tego stosują nagłówek Expires oraz Last-Modified, które moim zdaniem są w zupełności wystarczające. Pamiętaj jednak by kontrolować wartości tych nagłówków, co opiszę w następnym wpisie – w końcu nie wymaga to wiele pracy :-)
Osobiście – wyłączam etagi. Wszystko załatwiam Expires i Last-modified.