Etag czyli jeszcze jedna ciekawostka w HTTP

Jeśli url jest identyfikatorem zasobu to ETag oznacza jego kolejne wersje. Można pomyśleć o nim jak o dacie modyfikacji, tylko nie w formie daty a identyfikatora. Dzięki ETagowi możemy zapamiętać identyfikator wersji zasobu a później śledzić jego zmiany.

Jeśli odpytamy się o nasz zasób, możemy w nagłówkach otrzymać etag:

$ curl -iI http://moje.api/zasoby/zasobA
HTTP/1.1 200 OK
ETag: "686897696a7c876b7e"
ETag: W/"123456789A"

W odpowiedzi otrzymaliśmy dwa ETagi identyfikujące nasz zasób.

Silne i słabe ETagi

Pierwszy to silny ETag. Za każdym razem, gdy dostajemy ten sam silny ETag oznacza to, że nasz zasób jest identyczny bajt do bajtu.

Drugi, słaby ETag rozpoznajemy po przedrostku „W/”. Ten ETag się nie zmienia gdy nasz zasób nie zmienia się semantycznie. Oznacza to, że w praktycznym zastosowaniu dwie wersje z tym samym słabym ETagiem możemy stosować zamiennie ale niekoniecznie są one identyczne. Np. jeśli w kolejnej wersji artykułu poprawimy literówki. Kolejna wersja zdjęcia będzie miała lepszą kompresję itp. Dane się zmieniają ale ich sens nie.

ETag i warunkowy GET

Pisałem niedawno o warunkowej metodzie HTTP GET w oparciu o datę modyfikacji. Podobnie możemy zapytać, czy zasób zmienił się bazując na ETagach. Służy do tego nagłówek „If-None-Match”:

$ curl -i -h "If-None-Match: \"123456789A\"" http://moje.api/zasoby/zasobA
HTTP/1.1 304 Not Modified

Serwer nie wysłał nam żadnych danych tylko odpowiedział, że nasz zasób się nie zmienił. Jeśli wcześniej zapisaliśmy jego wersję w cache, nie musimy nic zmieniać. Gdyby zasób się zmienił, dostalibyśmy typową odpowiedź „200 OK”.

ETag i kontrola wersji

Nasz ETag może być też używany przy zapisie danych. Jeśli kilku klientów może modyfikować nasz zasób, istnieje szansa, że jeden nadpisze dane drugiego. ETag rozwiązuje ten problem. Możemy skorzystać z nagłówka „If-Match”, który działa odwrotnie do „If-None-Match”:

$ curl -i -X PUT -h "If-Match: \"123456789A\"" -d "jakieś dane" http://moje.api/zasoby/zasobA
HTTP/1.1 412 Precondition Failed

W tym przykładzie chcieliśmy zapisać nowe dane, np. poprawiliśmy trochę tekst na stronie itp, ale odkąd pobraliśmy poprzednią wersję tekstu ktoś ją zmienił. Serwer odpowiedział kodem 412 – błędny warunek. Dzięki temu nie nadpiszemy czyjejś pracy

Śledzenie użytkowników za pomocą ETagów

Niektóre serwisy nadużywają tej technologii. Przeglądarki odsyła ETagi do zasobów (np. obrazków) korzystając z nagłówka „If-None-Match”. Ponieważ to od serwera zależy jaki ETag poda klientowi, niektóre serwisy podają przy każdym zapytaniu inny ETag. Dzięki temu mogą śledzić poczynania użytkowników nawet przy wyłączonych ciasteczkach.

O śledzeniu za pomocą ETagów można poczytać w tym artykule.

Co dalej?

ETag to niedoceniana część HTTP. Możemy korzystać z niego przy wszystkich rodzajach zapytań. Tworząc serwis RESTowy ETag pozwala na zarządzanie wersjami i np. oszczędzanie łącza przy podawaniu dużych zasobów. Specyfikacja mówi, że serwer nie powinien wykonywać żadnych akcji na zasobie gdy dyrektywy If-Match lub If-None-Match nie są spełnione. Możemy więc kontrolować wersje.

Do poczytania jest przede wszystkim specyfikacja warunkowych zapytań w RFC 7232 oraz artykuł w wikipedii. Ponieważ ETag jest mało znany, każde wyszukanie w google od razu prowadzi nas do wartościowych opisów na jego temat.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *