HTTP 304 Not Modified to kod odpowiedzi z klasy 3xx, który mówi przeglądarce, że zasób nie zmienił się i można go wczytać z pamięci podręcznej.

To nie błąd, lecz mechanizm optymalizacyjny obniżający transfer i przyspieszający ładowanie stron.

Gdy jednak konfiguracja jest nieprawidłowa lub cache ulega uszkodzeniu, 304 może pojawiać się „bez powodu” i blokować dostęp do treści.

Podstawowe pojęcia – co to jest HTTP 304 i jak funkcjonuje w ekosystemie internetu

Definicja i klasyfikacja HTTP 304 Not Modified

HTTP 304 Not Modified zostało zdefiniowane w RFC 9110 (IETF) i służy do walidacji cache po stronie klienta.

304 nie sygnalizuje ani sukcesu, ani błędu – to informacja dla przeglądarki, że może użyć lokalnej kopii zasobu bez pobierania go z serwera.

Mechanizm ten wyraźnie redukuje obciążenie sieci i przyspiesza działanie serwisów, szczególnie przy wielu powtarzalnych żądaniach.

Anatomia warunkowego żądania HTTP

Podstawą 304 są warunkowe żądania, w których przeglądarka wysyła do serwera informacje o posiadanej wersji zasobu.

Mechanizm oparty o ETag wykorzystuje nagłówki ETag i If-None-Match. Jeśli wartości są zgodne, serwer odpowiada 304 i nie przesyła treści.

Mechanizm oparty o Last-Modified korzysta z Last-Modified i If-Modified-Since. Jeśli zasób nie zmienił się po wskazanej dacie, odpowiedzią również jest 304.

Przy odpowiedzi 304 serwer nie wysyła body, ale może dołączyć nagłówki aktualizujące politykę cache.

W odpowiedzi 304 najczęściej spotkasz następujące nagłówki:

  • cache-control,
  • expires,
  • etag,
  • vary.

Mechanika działania HTTP 304 w praktyce – od żądania do odpowiedzi

Sekwencja zdarzeń przy pierwszej wizycie na stronie

Przy pierwszym wejściu przeglądarka wysyła zwykłe żądanie i otrzymuje 200 OK z treścią oraz nagłówkami cache (Cache-Control, ETag, Last-Modified, Expires).

Następnie przechowuje zasób i metadane w pamięci podręcznej zgodnie z dyrektywą Cache-Control (np. max-age=3600).

Proces rewalidacji zasobów buforowanych

Po upływie ważności lub przy „odśwież” przeglądarka wysyła warunkowe żądanie z If-None-Match lub If-Modified-Since.

Jeśli wersja na serwerze jest identyczna, odpowiedź to 304; w przeciwnym razie serwer zwraca 200 z nową wersją i nagłówkami cache.

Nawet 20% żądań może kończyć się 304 – to realna oszczędność czasu i pasma, zwłaszcza przy właściwym użyciu dyrektywy immutable.

Przyczyny błędu HTTP 304 – kiedy optymalizacja staje się problemem

Rozróżnienie między legendarnym kodem 304 a problemowym „błędem 304”

Sam kod 304 nie jest błędem, ale błędy konfiguracji lub uszkodzony cache potrafią wywołać zjawisko „stale 304” – przeglądarka dostaje 304, lecz nie potrafi wyświetlić zawartości.

Do takich sytuacji prowadzą problemy po stronie serwera i/lub klienta:

  • Problemy po stronie serwera – błędna konfiguracja cache (np. mod_cache w Apache), niewłaściwe nagłówki Cache-Control, konfliktowe ETagi w środowisku z load balancerem, błędy DNS;
  • Problemy po stronie klienta – uszkodzony cache przeglądarki, złośliwe oprogramowanie ingerujące w ruch HTTP, wadliwe lub konfliktowe rozszerzenia przeglądarki.

Powszechne przyczyny związane z rejestracją i buforowaniem zasobów

Zbyt długie TTL-e (np. Cache-Control: max-age=31536000) dla często zmieniających się plików (CSS/JS) utrwalają stare wersje u użytkowników.

Niespójne ETagi (np. różne węzły za load balancerem generują inne wartości) uniemożliwiają prawidłową rewalidację albo powodują nieprzewidywalne 304.

Problemy DNS (stare wpisy, zainfekowany plik hosts) mogą kierować ruch do niewłaściwych serwerów i zwracać 304 wobec nieaktualnych zasobów.

Metody diagnostyki i lokalizowania przyczyn błędu HTTP 304

Używanie narzędzi deweloperskich przeglądarki do analizy nagłówków HTTP

Włącz narzędzia dev (F12) i w panelu Network porównaj nagłówki żądania/odpowiedzi, status i rozmiary.

W żądaniu szukaj If-None-Match i If-Modified-Since. W odpowiedzi zweryfikuj Cache-Control, ETag, Last-Modified, Expires, Vary.

Oto zestaw nagłówków, na których warto skupić uwagę podczas analizy:

  • if-none-match,
  • if-modified-since,
  • cache-control,
  • etag,
  • last-modified,
  • expires,
  • vary.

W Firefox możesz testować tryb offline; w Safari włącz menu Develop, by dostać się do narzędzi.

Testowanie i walidacja za pomocą narzędzi online

curl pozwala wysyłać żądania warunkowe i sprawdzać odpowiedź serwera:

curl --http1.1 -I --header 'If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT' https://example.com

Użyj też GTmetrix i Google PageSpeed Insights, aby wykrywać braki w nagłówkach cache i problemy z rewalidacją.

Kompleksowe strategie rozwiązywania problemów z HTTP 304

Działania po stronie klienta – szybka ścieżka naprawy

Jeśli 304 blokuje wyświetlanie treści, wykonaj następujące kroki w podanej kolejności:

  1. Wyczyść pamięć podręczną i pliki cookie przeglądarki (zakres: cały czas).
  2. Wykonaj „hard refresh” strony (Windows: Ctrl+F5 / Ctrl+Shift+R; macOS: Cmd+Shift+R).
  3. Wyłącz rozszerzenia (szczególnie adblock, VPN/proxy, narzędzia debug) i sprawdź stronę ponownie.
  4. Przeskanuj system pod kątem malware (Windows Defender, narzędzie czyszczenia w Chrome pod chrome://settings/cleanup).
  5. Wyczyść cache DNS i odśwież połączenie sieciowe.
  6. Sprawdź zachowanie w innej przeglądarce/profilu użytkownika.

Najczęściej winny jest uszkodzony cache lub konfliktujące rozszerzenie – dlatego zaczynaj od tych kroków.

Usuwanie złośliwego oprogramowania i rozszerzenia przeglądarki

W Chrome użyj chrome://settings/cleanup, w Windows skorzystaj z Windows Defendera.

Wyłączaj rozszerzenia pojedynczo (chrome://extensions, about:addons) i po każdym teście sprawdzaj stronę. Winne usuń lub zaktualizuj.

Czyszczenie DNS i resetowanie TCP/IP

Odśwież lokalny cache DNS, by wyeliminować stare wpisy kierujące na niewłaściwe IP.

Windows:

ipconfig /flushdns

macOS:

sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

Linux: zrestartuj usługę DNS właściwą dla używanego resolvera (np. systemd-resolved, dnsmasq).

Możesz też tymczasowo przełączyć się na Google DNS (8.8.8.8, 8.8.4.4), aby wykluczyć problemy po stronie dostawcy.

Działania po stronie serwera – konfiguracja Apache i Nginx

W Apache przejrzyj konfigurację mod_cache oraz politykę dla zasobów dynamicznych/statycznych.

Pliki konfiguracyjne: /etc/apache2/httpd.conf, /etc/apache2/apache2.conf. Po zmianach wykonaj restart:

sudo systemctl restart apache2

W Nginx zweryfikuj proxy_cache_path, proxy_cache, proxy_cache_valid oraz uprawnienia do katalogu cache (np. /var/cache/nginx).

Korekta ustawień Cache-Control i nagłówków buforowania

Właściwe dyrektywy Cache-Control zapobiegają „stale 304” i poprawiają wydajność. Poniżej praktyczne warianty i zastosowania:

Kategoria zasobu Przykładowy nagłówek Typowe zastosowanie Efekt
Statyczne, rzadko zmieniane Cache-Control: public, max-age=31536000, immutable obrazy, czcionki, skompilowane JS/CSS maksymalna wydajność bez rewalidacji
Półstatyczne Cache-Control: public, max-age=0, must-revalidate artykuły, strony informacyjne regularna rewalidacja, częste 304 zamiast 200
Zawsze dynamiczne Cache-Control: no-store API, treści generowane per żądanie brak przechowywania po stronie klienta
Dane prywatne Cache-Control: private, no-cache zasoby specyficzne dla użytkownika cache tylko w przeglądarce, rewalidacja wymagana

Optymalizacja buforowania – strategie maksymalizowania wydajności

Implementacja entity tags (ETags)

Konsekwentne ETagi są kluczowe, zwłaszcza w środowiskach z wieloma węzłami za load balancerem.

Rozważ generowanie ETagów z hashów zawartości lub wersjonowanie plików – unikniesz rozbieżności między serwerami.

Przykład w Node.js (ETag na bazie MD5 treści):

const crypto = require('crypto');

app.get('/api/data', (req, res) => {

const data = JSON.stringify({ message: 'Hello, world!' });

const etag = crypto.createHash('md5').update(data).digest('hex');

res.setHeader('ETag', `"${etag}"`);

res.setHeader('Cache-Control', 'max-age=3600');

if (req.headers['if-none-match'] === `"${etag}"`) {

res.status(304).end();

} else {

res.json(JSON.parse(data));

}

});

Strategia unieważniania cache’u dla zasobów statycznych

Cache busting (hash w nazwie pliku lub parametrze wersji) wymusza pobranie nowej wersji po zmianie treści.

Przykład: styles.a1b2c3d4.css zamiast styles.css lub styles.css?v=1.0.5.

Popularne narzędzia buildujące, które automatycznie dodają hash do nazw plików, to między innymi:

  • webpack,
  • rollup,
  • parcel.

Integracja CDN i pamięci podręcznych reverse proxy

CDN (np. Cloudflare, Akamai, AWS CloudFront) skraca drogę do zasobów i odciąża serwer źródłowy.

Reverse proxy cache (np. Varnish) serwuje odpowiedzi z bliskiego cache, a dyrektywa s-maxage pozwala sterować TTL-em dla cache współdzielonych.

Łącz dyrektywy przeglądarkowe i CDN-owe (np. stale-while-revalidate), aby równoważyć świeżość i wydajność.

Zapobieganie problemom – najlepsze praktyki zarządzania buforowaniem

Testowanie i monitorowanie konfiguracji buforowania

Regularnie testuj rewalidację skryptami (curl, wget) i monitoruj raporty z GTmetrix oraz PageSpeed Insights.

Weryfikuj statusy 304/200 po zmianach w konfiguracji, by szybko wykrywać niepożądane zachowania.

Dokumentacja i standaryzacja polityki buforowania

Ustal i udokumentuj politykę cache dla kategorii zasobów: statyczne, półstatyczne, dynamiczne, prywatne.

Wdrażaj zmiany etapowo (staging → produkcja) i miej checklistę testów, aby uniknąć regresji wydajności i błędów 304.