Logo David Burdelak
Webdevelopment

Jak naprawić pętlę przekierowań URL krok po kroku?

Naprawa pętli przekierowań URL na serwerze i w kodzie strony

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:

WarstwaGdzie sprawdzamJak rozpoznać w nagłówkach
CDN lub proxyreguły przekierowań i tryb SSL w panelu, np. Cloudflarenagłówki server: cloudflare, cf-ray
Serwer WWWplik .htaccess, konfiguracja Nginxnagłówek server: Apache lub nginx, brak nagłówków aplikacji
CMSadres strony w ustawieniach, wtyczki do przekierowań i SSLnagłówki typowe dla CMS, np. x-redirect-by: WordPress
Kod aplikacjimiddleware wymuszające HTTPS, przekierowania językowenagłó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://, z www i 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.