ETag w aplikacjach — co to jest, przeznaczenie i zasada

Autor: IT Sectr Opublikowano: 2026-06-14 Czas czytania: 7 min

ETag — nagłówek odpowiedzi HTTP zawierający unikalny identyfikator wersji zasobu. Serwer generuje ETag jako hash treści lub numer wersji i zwraca go klientowi wraz z danymi. Przy kolejnych żądaniach klient wysyła ten identyfikator w nagłówku If-None-Match, umożliwiając serwerowi sprawdzenie, czy zasób się zmienił. Według MDN Web Docs, 2025, ETag stanowi podstawę mechanizmu warunkowych żądań GET w HTTP. Żądania warunkowe z ETag zmniejszają ilość przesyłanych danych podczas synchronizacji aplikacji mobilnych nawet o 90%.

Najważniejsze

  • ETag — nagłówek HTTP zawierający unikalny identyfikator wersji zasobu, zazwyczaj hash jego treści.
  • If-None-Match — klient wysyła zapisany ETag, serwer zwraca 304 Not Modified, jeśli zasób się nie zmienił.
  • Oszczędność ruchu — żądania warunkowe z ETag redukują ilość danych podczas synchronizacji aplikacji mobilnych, ponieważ treść odpowiedzi nie jest przesyłana.
  • Silne i słabe ETag — silne rozróżniają zawartość bajt po bajcie, słabe dopuszczają semantyczną równoważność zasobu.
  • Zastosowanie — ETag jest używany w REST API do synchronizacji danych, buforowania i zapobiegania konfliktom edycji.

Czym jest ETag w HTTP i aplikacjach mobilnych?

ETag (Entity Tag) — nagłówek HTTP z rodziny nagłówków warunkowych, zapewniający walidację buforowanych zasobów. Serwer oblicza ETag jako sumę hash (MD5, SHA-256) lub numer wersji zasobu i zwraca go w odpowiedzi na żądanie GET. Klient zapisuje ETag wraz z danymi i przy ponownym żądaniu wysyła go w nagłówku If-None-Match. Jeśli zawartość zasobu się nie zmieniła, serwer odpowiada statusem 304 Not Modified bez treści odpowiedzi.

Dla aplikacji mobilnych ETag jest krytyczny, ponieważ zmniejsza ilość pobieranych danych. Przy każdym uruchomieniu lub synchronizacji aplikacja sprawdza aktualność zasobów żądaniem z If-None-Match — zamiast pełnego pobierania danych otrzymuje 304 i korzysta z lokalnej kopii. Według Google Chrome Team (2024), użycie ETag w mobilnych API redukuje średni rozmiar odpowiedzi o 87% dla list i o 94% dla pojedynczych obiektów.

ETag jest generowany po stronie serwera i może być zarówno deterministyczny (taki sam dla identycznej treści, co jest przydatne dla współdzielonych pamięci podręcznych), jak i unikalny dla każdej odpowiedzi (do ścisłej walidacji). W REST API przeznaczonych do synchronizacji mobilnej najczęściej stosuje się kombinację hasha treści i numeru wersji rekordu w bazie danych.

Typy ETag: silne i słabe identyfikatory

Silne ETag (strong ETag) — identyfikatory, które zmieniają się przy każdej zmianie zawartości, w tym nieznacznych (spacje, formatowanie). Format: "abc123def" (w cudzysłowie, bez prefiksu). Silne ETag gwarantują, że zasób nie zmienił się bajt po bajcie. Są wymagane dla żądań zakresowych (Range requests) i do weryfikacji integralności częściowych pobrań.

Słabe ETag (weak ETag) — identyfikatory z prefiksem W/, na przykład W/"abc123def". Dopuszczają, że zasób jest semantycznie równoważny, nawet jeśli reprezentacja bajtowa się różni. Słabe ETag są przydatne dla serwerów, które dynamicznie generują odpowiedzi z różnymi spacjami lub formatowaniem, ale o tym samym znaczeniu. Jednak słabe ETag nie obsługują żądań zakresowych.

Porównanie typów ETag:

CechaSilny ETagSłaby ETag
Format"hash"W/"hash"
CzułośćBajt po bajcieSemantyczna
Żądania zakresoweObsługiwaneNieobsługiwane
Buforowanie CDNIdealneOgraniczone
SynchronizacjaWysoka dokładnośćDopuszcza kolizje

ETag kontra Last-Modified: co wybrać

Last-Modified — nagłówek HTTP wskazujący datę i czas ostatniej modyfikacji zasobu. Klient wysyła go z powrotem w nagłówku If-Modified-Since. Last-Modified jest prostszy w implementacji (serwer potrzebuje tylko daty), ale ma fundamentalne ograniczenia: rozdzielczość jednej sekundy (dwie zmiany w ciągu jednej sekundy są nierozróżnialne) i niemożność określenia, czy zawartość zmieniła się przy tej samej dacie (na przykład po przywróceniu z kopii zapasowej).

ETag rozwiązuje te problemy: hash treści zmienia się przy każdej zmianie niezależnie od czasu. Dlatego nowoczesne REST API używają kombinacji obu nagłówków: ETag do precyzyjnej walidacji i Last-Modified do przybliżonej filtracji w CDN. Apache HTTP Server i Nginx domyślnie generują oba nagłówki dla plików statycznych.

Dla aplikacji mobilnych z synchronizacją ETag jest kluczowy, ponieważ umożliwia wykrywanie konfliktów edycji. Jeśli klient wysyła PUT z nagłówkiem If-Match: "etag", serwer odrzuca żądanie, jeśli zasób został zmieniony przez innego klienta (optymistyczne blokowanie). Last-Modified nie może zagwarantować takiej niezawodności ze względu na dokładność co do sekundy.

Przykłady pracy z ETag w Kotlin

Rozważmy implementację kliencką ETag w aplikacji mobilnej w Kotlin z użyciem Retrofit i OkHttp. Przy każdym żądaniu GET klient zapisuje ETag z odpowiedzi, a przy następnym żądaniu wysyła go w nagłówku If-None-Match. Jeśli serwer zwróci 304, dane nie są pobierane ponownie.

Konfiguracja klienta OkHttp z buforowaniem ETag:

kotlin
class EtagClient {
    private val etagCache =
        mutableMapOf<String, String>()

    private val client = OkHttpClient.Builder().build()

    suspend fun fetchWithEtag(
        url: String
    ): Result<String> {
        val request = Request.Builder()
            .url(url)
            .header("If-None-Match",
                etagCache[url] ?: "")
            .build()

        val response = client.newCall(request).await()

        return when (response.code) {
            304 -> Result.success(
                "not_modified")
            200 -> {
                response.header("ETag")?.let {
                    etagCache[url] = it
                }
                Result.success(response.body?.string()
                    ?: "")
            }
            else -> Result.failure(
                Exception("HTTP ${response.code}"))
        }
    }
}

Klient zapisuje ETag po udanej odpowiedzi 200 i wysyła go w nagłówku If-None-Match przy następnym żądaniu. Przy 304 klient wie, że lokalna wersja jest aktualna i nie marnuje ruchu na ponowne pobieranie danych. Ten wzorzec redukuje koszty sieciowe aplikacji mobilnej o 80–90% dla często żądanych zasobów.

Rola ETag w synchronizacji aplikacji mobilnych

ETag jest kluczowym mechanizmem optymalizacji synchronizacji aplikacji mobilnych z REST API. W standardowym schemacie synchronizacji klient najpierw żąda listy zasobów z walidacją ETag — jeśli żaden zasób się nie zmienił, serwer zwraca 304 i klient kończy synchronizację. Jeśli są zmiany, serwer zwraca tylko zmodyfikowane zasoby. Takie podejście nazywa się deltową synchronizacją i jest krytyczne dla urządzeń mobilnych z ograniczonym ruchem.

W scenariuszach z optymistycznym blokowaniem ETag służy do zapobiegania konfliktom Lost Update. Gdy klient wysyła PUT w celu aktualizacji zasobu, dołącza nagłówek If-Match: "etag". Jeśli ETag nie jest zgodny (inny klient już zmienił zasób), serwer odpowiada 412 Precondition Failed, a klient musi ponownie pobrać aktualną wersję i powtórzyć zmianę. To podejście zapewnia spójność danych bez blokad na poziomie bazy danych.

Dla systemów rozproszonych z trybem offline ETag jest używany w połączeniu z Conflict Resolution. Klient synchronizuje się, pobierając aktualne ETag dla wszystkich zasobów. Przy wysyłaniu zmian serwer sprawdza If-Match — jeśli ETag się nie zgadza, rejestrowany jest konflikt, który jest rozwiązywany według wybranej strategii (LWW, Merge). Według Postman API Report (2025), 67% produkcyjnych REST API dla aplikacji mobilnych używa ETag jako głównego mechanizmu walidacji wersji.

Często zadawane pytania

Czym jest nagłówek HTTP ETag?

ETag — nagłówek odpowiedzi HTTP zawierający unikalny identyfikator wersji zasobu. Klient używa go do żądań warunkowych: jeśli zasób się nie zmienił, serwer zwraca 304 Not Modified bez treści odpowiedzi, oszczędzając ruch.

Jaka jest różnica między ETag a Last-Modified?

ETag używa hasha treści do dokładnego porównania. Last-Modified opiera się na dacie modyfikacji z dokładnością do sekundy. ETag jest bardziej niezawodny do wykrywania rzeczywistych zmian i obsługuje optymistyczne blokowanie przez If-Match.

Czym są silne i słabe ETag?

Silne ETag (bez prefiksu) rozróżniają zasoby bajt po bajcie. Słabe ETag (z prefiksem W/) dopuszczają semantyczną równoważność. Silne są wymagane dla żądań zakresowych, słabe — dla dynamicznie generowanej treści.

Jak ETag pomaga w synchronizacji mobilnej?

ETag redukuje ruch o 80–90%: klient sprawdza aktualność wszystkich zasobów przez If-None-Match, pobierając tylko zmienione. Bez ETag klient pobierałby pełne dane przy każdej synchronizacji, marnując ruch i baterię.

Jak zaimplementować ETag na serwerze?

Serwer oblicza ETag jako hash (MD5, SHA-256) treści odpowiedzi lub używa numeru wersji rekordu z bazy danych. W Spring Boot wystarczy adnotacja @Cacheable z etag = true. W Express.js — middleware etag jest domyślnie włączony.

Podsumowanie

  • ETag — nagłówek HTTP do walidacji wersji zasobów, oparty na hashu treści lub numerze wersji.
  • Żądania warunkowe — klient wysyła If-None-Match z zapisanym ETag, serwer odpowiada 304 przy braku zmian.
  • Typy ETag — silne (bajt po bajcie, dla żądań zakresowych) i słabe (równoważność semantyczna, prefiks W/).
  • Zaleta — ETag jest dokładniejszy niż Last-Modified, ponieważ hash zmienia się przy każdej zmianie treści niezależnie od czasu.
  • Optymistyczne blokowanie — przez If-Match ETag zapobiega konfliktom Lost Update przy współbieżnej edycji zasobów.
  • Synchronizacja deltowa — na ETag opierają się schematy synchronizacji, w których przesyłane są tylko zmienione zasoby.
  • Zalecenie — zawsze dodawaj ETag w REST API dla aplikacji mobilnych. Łącz z Last-Modified dla zgodności z CDN i serwerami proxy.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również