Komunikat ERR_TOO_MANY_REDIRECTS oznacza, że przeglądarka krąży między adresami, które przekierowują się nawzajem, i po
kilkunastu próbach się poddaje. Strona jest wtedy niedostępna dla wszystkich, łącznie z robotami wyszukiwarek. Pętle naprawiałem już
dziesiątki razy, najczęściej po włączeniu CDN, zmianie certyfikatu, migracji albo instalacji wtyczki do przekierowań. W tym wpisie pokazuję,
jak krok po kroku ustalam, które reguły się ze sobą kłócą, i jak je naprawiam.
Krok 1. Sprawdzam cały łańcuch przekierowań
Nie testuję pętli w zwykłym oknie przeglądarki, bo zapamiętane przekierowania 301 i ciasteczka mogą pokazywać problem, którego już nie ma, albo ukrywać aktualny. Zaczynam od terminala:
curl -sIL --max-redirs 10 https://twojadomena.pl/ | grep -iE "^(HTTP|location)"
Wynik pokazuje każdy krok z kodem odpowiedzi i adresem docelowym. Typowa pętla wygląda tak:
HTTP/2 301
location: https://twojadomena.pl/
HTTP/2 301
location: http://twojadomena.pl/
HTTP/2 301
location: https://twojadomena.pl/
Już z tego widać, czego dotyczy konflikt: protokołu (HTTP i HTTPS), wersji z www i bez, ukośnika na końcu adresu czy języka
lub kraju. Jeśli pętla pojawia się tylko w przeglądarce, a curl jej nie pokazuje, przyczyną są zwykle ciasteczka, np. zapamiętany wybór
języka, więc sprawdzam stronę w oknie incognito.
Krok 2. Ustalam, kto wysyła przekierowania
Przekierowanie może pochodzić z kilku warstw, a pętla powstaje prawie zawsze, gdy dwie z nich wymuszają przeciwny stan:
| Warstwa | Gdzie sprawdzam | Jak rozpoznać w nagłówkach |
|---|---|---|
| CDN lub proxy | reguły przekierowań i tryb SSL w panelu, np. Cloudflare | nagłówki server: cloudflare, cf-ray |
| Serwer WWW | plik .htaccess, konfiguracja Nginx | nagłówek server: Apache lub nginx, brak nagłówków aplikacji |
| CMS | adres strony w ustawieniach, wtyczki do przekierowań i SSL | nagłówki typowe dla CMS, np. x-redirect-by: WordPress |
| Kod aplikacji | middleware wymuszające HTTPS, przekierowania językowe | nagłówki frameworka lub własne |
Przy większych serwisach przydaje się też analiza logów serwera, która pokazuje, czy żądania w ogóle docierają do serwera i z jakim protokołem.
Krok 3. Najczęstsze przyczyny i ich naprawa
CDN w trybie Flexible i wymuszanie HTTPS na serwerze
To przyczyna numer jeden. Cloudflare w trybie Flexible przyjmuje od użytkownika połączenie HTTPS, ale z serwerem łączy się przez HTTP. Serwer widzi HTTP, przekierowuje na HTTPS, a CDN znowu łączy się przez HTTP. Rozwiązanie: zainstalować certyfikat na serwerze, np. darmowy z Let's Encrypt, i przełączyć tryb SSL w Cloudflare na Full (strict). Pozostałe reguły przekierowań w CDN ustawiam tak, żeby nie dublowały się z serwerem. Sprawdzam to przy każdej konfiguracji CDN.
Aplikacja za proxy nie widzi HTTPS
Gdy przed serwerem stoi proxy lub load balancer, aplikacja dostaje żądanie przez HTTP, nawet jeśli użytkownik połączył się przez HTTPS.
Kod wymuszający HTTPS przez sprawdzenie $_SERVER['HTTPS'] przekierowuje wtedy w nieskończoność. Informację o oryginalnym
protokole przekazuje nagłówek X-Forwarded-Proto:
// PHP: rozpoznanie HTTPS za zaufanym proxy
if (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https') {
$_SERVER['HTTPS'] = 'on';
}
W WordPressie ten fragment dodaję na początku pliku wp-config.php, w Laravelu konfiguruję zaufane proxy w middleware
TrustProxies. Nagłówkowi ufam tylko wtedy, gdy ruch faktycznie przechodzi przez moje proxy, bo inaczej każdy może go podrobić.
Sprzeczne reguły na serwerze i w CMS
Serwer przekierowuje na wersję bez www, a w ustawieniach WordPressa adres strony ma www. Albo serwer usuwa ukośnik
na końcu adresu, a CMS go dodaje. Naprawiam to, ustalając jedną wersję adresu i ustawiając ją wszędzie: w ustawieniach CMS, regułach
serwera i regułach CDN. Na Apache przekierowania na HTTPS i wersję bez www łączę w jedną regułę, która uwzględnia proxy:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
Gdy nie mam dostępu do panelu WordPressa, bo pętla obejmuje też logowanie, adres strony ustawiam tymczasowo stałymi WP_HOME
i WP_SITEURL w wp-config.php.
Wtyczki i przekierowania zależne od ciasteczek
Wtyczki do SSL, cache i przekierowań potrafią dodawać własne reguły do .htaccess, które kłócą się z istniejącymi. Gdy łańcuch
wskazuje na CMS, wyłączam wtyczki, zmieniając nazwę ich katalogu, i włączam je pojedynczo. Osobną grupą są przekierowania według języka
lub kraju zapisywane w ciasteczku. Jeśli ciasteczko ustawia się na innej domenie lub ścieżce, niż jest sprawdzane, użytkownik krąży między
wersjami językowymi.
Po naprawie
Po usunięciu pętli przechodzę przez krótką listę kontrolną:
- sprawdzam wszystkie warianty adresu:
http://,https://, zwwwi bez, z ukośnikiem i bez; każdy powinien trafiać do adresu docelowego jednym przekierowaniem, - testuję logowanie, koszyk i zmianę języka, bo te miejsca najczęściej mają własne przekierowania,
- w Search Console sprawdzam kluczowe adresy narzędziem do sprawdzania adresów URL i zlecam ponowne zindeksowanie, jeśli pętla trwała dłużej,
- poprawiam linki wewnętrzne, żeby prowadziły od razu do właściwej wersji adresu, bo każde zbędne przekierowanie marnuje crawl budget,
- czyszczę pamięć podręczną CDN i cache stron, żeby nie serwowały zapamiętanych przekierowań.
Pętle najczęściej powstają przy zmianach infrastruktury, dlatego przy każdej przeprowadzce testuję przekierowania na kopii strony, zanim przełączę domenę. Ten test jest stałym punktem każdej migracji strony internetowej.