Przekierowania w .htaccess — bezpieczny poradnik z przykładami 301, HTTPS i www
Plik .htaccess pozwala ustawić przekierowania bez edycji głównej konfiguracji serwera Apache. Jedna zła reguła może jednak wywołać błąd 500, pętlę przekierowań albo odciąć stronę. Poniżej znajdziesz bezpieczne przykłady dla najczęstszych sytuacji oraz sposób ich testowania i cofnięcia.
Krótka odpowiedź: dla pojedynczego, prostego przekierowania użyj dyrektywy
Redirect 301. Gdy potrzebujesz warunku — na przykład rozpoznania domeny, protokołu HTTPS albo wzorca wielu adresów — użyjRewriteCondiRewriteRule. Zrób kopię.htaccess, zmieniaj jedną rzecz naraz i po każdej zmianie sprawdzaj kod odpowiedzi oraz docelowy adres.
Zanim wkleisz kod: kiedy .htaccess w ogóle działa?
.htaccess jest plikiem konfiguracyjnym używanym przede wszystkim przez serwer Apache. Reguły przepisywania Apache obsługuje również LiteSpeed, często spotykany na hostingach WordPress. Nginx nie odczytuje .htaccess — tam przekierowania umieszcza się w konfiguracji serwera albo ustawia w panelu hostingu.
Żeby reguły mod_rewrite zadziałały, hosting musi pozwalać na ich użycie, a moduł musi być aktywny. Na hostingu współdzielonym zwykle jest to już skonfigurowane. Oficjalna dokumentacja Apache wskazuje, że w konfiguracji serwera wymagane jest co najmniej AllowOverride FileInfo. Jeżeli plik jest odczytywany, ale reguły przepisywania są niedozwolone, potrzebna będzie pomoc administratora hostingu.
Przed zmianą wykonaj cztery czynności:
- Pobierz kopię obecnego
.htaccessna komputer. - Upewnij się, że masz dostęp do plików przez panel hostingu lub SFTP. Dostęp tylko przez panel WordPress nie wystarczy, jeśli strona przestanie się otwierać.
- Spisz obecny adres i oczekiwany adres docelowy.
- Zmieniaj i testuj po jednej regule.
Jeżeli po zapisaniu pliku pojawi się błąd 500, przywróć kopię. Nie próbuj naprawiać kilku nowych reguł jednocześnie.
Gdzie znajduje się .htaccess?
W typowej instalacji WordPress plik znajduje się w głównym katalogu strony — tym samym, w którym są katalogi wp-admin, wp-content, wp-includes oraz plik wp-config.php.
Nazwa zaczyna się od kropki, dlatego menedżer plików może go ukrywać. W panelu hostingu poszukaj opcji „pokaż ukryte pliki”. Jeżeli pliku nie ma, nie twórz go automatycznie bez sprawdzenia, czy serwer rzeczywiście używa Apache lub LiteSpeed i czy domena wskazuje na ten katalog.
W WordPressie zwykle zobaczysz blok podobny do tego:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Dokładna zawartość może się różnić. Nie zastępuj swojego bloku kodem z tego przykładu. WordPress może nadpisywać zawartość pomiędzy komentarzami # BEGIN WordPress i # END WordPress. Własne reguły dodawaj przed tym blokiem, poza jego znacznikami.
Redirect czy RewriteRule?
Apache ma dwa popularne mechanizmy:
RedirectiRedirectMatchz modułumod_alias— prostsze przekierowania;RewriteRuleorazRewriteCondz modułumod_rewrite— reguły warunkowe i dopasowania wzorców.
Oficjalna dokumentacja Apache zaleca prostszy Redirect, jeśli zadanie nie wymaga pełnej mocy mod_rewrite. Nie mieszaj obu mechanizmów dla tego samego adresu. Ich kolejność przetwarzania zależy od miejsca konfiguracji i może być źródłem trudnych do zauważenia konfliktów.
Praktyczna zasada:
| Potrzeba | Wybór |
|---|---|
| Jeden stary adres ma prowadzić do jednego nowego | Redirect 301 |
| Cały katalog ma przejść pod nowy prefiks | Redirect 301 lub RedirectMatch |
| Reguła zależy od domeny, HTTPS, parametrów albo kilku warunków | RewriteCond + RewriteRule |
| Wzorzec ma zachować zmienne fragmenty adresu | RewriteRule albo RedirectMatch |
Jak zrobić pojedyncze przekierowanie 301?
Załóżmy, że stary artykuł był pod adresem:
https://example.pl/stara-oferta/
a teraz jego właściwy odpowiednik znajduje się tutaj:
https://example.pl/nowa-oferta/
Precyzyjna reguła dopasowująca tylko ten adres (z opcjonalnym końcowym ukośnikiem):
RedirectMatch 301 "^/stara-oferta/?$" "https://example.pl/nowa-oferta/"
Kod 301 oznacza trwałe przeniesienie zasobu. Używaj go, gdy stary adres ma zostać zastąpiony na stałe. Prostsza dyrektywa Redirect 301 /stara-oferta/ ... działa prefiksowo i może objąć także adresy z dalszą częścią ścieżki, dlatego przy wymaganiu dokładnego dopasowania bezpieczniejszy jest powyższy RedirectMatch albo precyzyjny RewriteRule. Nie przekierowuj wszystkich usuniętych stron na stronę główną — przekierowanie powinno prowadzić do najbliższego odpowiednika. Jeżeli odpowiednika nie ma, prawidłowa odpowiedź 404 lub 410 może być uczciwsza niż mylący redirect.
Ten sam przypadek można zapisać przez mod_rewrite:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^stara-oferta/?$ /nowa-oferta/ [R=301,L]
</IfModule>
W .htaccess wzorzec RewriteRule zwykle nie zaczyna się od ukośnika. ^ oznacza początek dopasowania, $ jego koniec, a /? pozwala obsłużyć wariant z końcowym ukośnikiem i bez niego.
Flagi:
R=301wysyła zewnętrzne przekierowanie 301;Lkończy bieżące przetwarzanie reguł po dopasowaniu.
Jak przekierować HTTP na HTTPS?
Najpierw certyfikat SSL musi być aktywny dla domeny. Przekierowanie nie naprawi brakującego ani nieważnego certyfikatu.
W typowej konfiguracji Apache można użyć:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://example.pl%{REQUEST_URI} [R=301,L]
</IfModule>
Zastąp example.pl prawdziwą domeną. %{REQUEST_URI} zachowuje ścieżkę, więc /oferta/ przejdzie na https://example.pl/oferta/.
Uwaga: jeżeli strona działa za proxy, CDN-em lub panelem, który kończy połączenie SSL przed Apache, zmienna %{HTTPS} może mieć wartość „off”, mimo że użytkownik korzysta z HTTPS. Powyższa reguła może wtedy stworzyć pętlę. Nie kopiuj przypadkowej reguły opartej na X-Forwarded-Proto, jeżeli nie wiesz, czy nagłówek jest ustawiany przez zaufane proxy. W takiej architekturze bezpieczniej użyć funkcji hostingu/CDN-u albo dokumentacji dostawcy.
Jak przekierować www na domenę bez www?
Jeśli wybrany adres kanoniczny to https://example.pl, użyj:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.pl$ [NC]
RewriteRule ^ https://example.pl%{REQUEST_URI} [R=301,L]
</IfModule>
NC oznacza dopasowanie bez rozróżniania wielkości liter. Kropki w nazwie domeny są poprzedzone ukośnikiem odwrotnym, ponieważ we wzorcu wyrażenia regularnego zwykła kropka ma specjalne znaczenie.
Certyfikat SSL powinien obejmować także wersję www. Przeglądarka musi najpierw zestawić bezpieczne połączenie ze źródłowym hostem, zanim odbierze przekierowanie.
Jak przekierować wersję bez www na www?
Jeżeli docelowym wariantem jest https://www.example.pl:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.pl$ [NC]
RewriteRule ^ https://www.example.pl%{REQUEST_URI} [R=301,L]
</IfModule>
Nie ustawiaj jednocześnie reguły w przeciwną stronę w hostingu, CDN-ie albo wtyczce. Dwie sprzeczne konfiguracje są częstą przyczyną ERR_TOO_MANY_REDIRECTS.
Jak przekierować starą domenę na nową i zachować ścieżki?
Chcesz uzyskać taki efekt:
https://stara-domena.pl/oferta/a/
→ https://nowa-domena.pl/oferta/a/
Reguła umieszczona na serwerze obsługującym starą domenę może wyglądać tak:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?stara-domena\.pl$ [NC]
RewriteRule ^ https://nowa-domena.pl%{REQUEST_URI} [R=301,L]
</IfModule>
To rozwiązanie ma sens tylko wtedy, gdy struktura adresów w obu serwisach jest taka sama. Po migracji z nową strukturą przygotuj mapę stary URL → właściwy nowy URL. Automatyczne kierowanie wszystkiego według tej samej ścieżki może stworzyć setki przekierowanych błędów 404.
Stara domena musi pozostać aktywna, wskazywać na serwer z regułą i mieć ważny certyfikat SSL. Przekierowania nie będą działały po wygaśnięciu domeny.
Jak przekierować cały katalog?
Przykład: wszystko spod /stare-uslugi/ ma trafić pod /uslugi/ z zachowaniem dalszej części adresu.
Prosta wersja z Redirect:
Redirect 301 /stare-uslugi/ https://example.pl/uslugi/
Dyrektywa Redirect działa prefiksowo i dołącza dalszą część ścieżki. Przed publikacją sprawdź kilka adresów zagnieżdżonych, nie tylko katalog główny.
Wersja z RewriteRule:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^stare-uslugi/(.*)$ /uslugi/$1 [R=301,L]
</IfModule>
Fragment dopasowany przez (.*) jest dostępny jako $1.
301, 302, 307 czy 308?
Najczęściej spotkasz cztery kody:
| Kod | Znaczenie | Typowe zastosowanie |
|---|---|---|
| 301 | przeniesienie trwałe | trwała zmiana adresu strony |
| 302 | przeniesienie tymczasowe | docelowy adres ma wrócić do poprzedniego |
| 307 | tymczasowe, z zachowaniem metody HTTP | tymczasowe przekierowanie żądań innych niż zwykły GET |
| 308 | trwałe, z zachowaniem metody HTTP | trwałe przeniesienie, gdy metoda i ciało żądania nie mogą się zmienić |
Według dokumentacji HTTP kody 307 i 308 jednoznacznie zachowują metodę żądania. To ma znaczenie np. dla żądań POST. Dla zwykłej zmiany adresu publicznej podstrony najczęściej używa się 301.
Nie wybieraj kodu na podstawie mitu o „mocy SEO”. Kod ma prawdziwie opisywać sytuację: trwałą albo tymczasową.
Gdzie umieścić reguły na stronie WordPress?
Własne reguły RewriteRule dodaj przed blokiem WordPress:
# Własne przekierowania — początek
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^stara-oferta/?$ /nowa-oferta/ [R=301,L]
</IfModule>
# Własne przekierowania — koniec
# BEGIN WordPress
# ...reguły generowane przez WordPress...
# END WordPress
Dlaczego przed? Standardowa reguła WordPress kieruje nieistniejące ścieżki do index.php. Własne, precyzyjne przekierowania powinny zostać ocenione wcześniej. Nie wstawiaj ich wewnątrz automatycznie zarządzanego bloku, bo mogą zniknąć po zapisaniu ustawień permalinków albo zmianie konfiguracji.
RewriteEngine On może pojawić się w pliku więcej niż raz, ale dla czytelności lepiej grupować własne reguły w jednym bloku.
Jak testować przekierowanie?
Nie ograniczaj testu do wpisania adresu w przeglądarce. Przeglądarka może pamiętać 301 i pokazać wynik starej konfiguracji.
Test pojedynczej odpowiedzi
curl -I https://example.pl/stara-oferta/
Oczekiwany fragment:
HTTP/2 301
location: https://example.pl/nowa-oferta/
Test całego łańcucha
curl -IL https://example.pl/stara-oferta/
Polecenie pokaże kolejne odpowiedzi aż do strony docelowej. Dobry wynik to zwykle jedno przekierowanie i na końcu 200. Jeśli widzisz kilka kroków — np. HTTP → HTTPS → www → nowy adres → końcowy ukośnik — uporządkuj reguły, aby prowadziły od razu do wersji docelowej.
Sprawdź również:
- adres z końcowym ukośnikiem i bez niego;
- wersję HTTP oraz HTTPS;
wwwi wariant bezwww;- parametr zapytania, jeśli może się pojawić;
- dwa lub trzy zagnieżdżone adresy przy regule katalogowej;
- stronę docelową — czy zwraca 200 i nie kieruje dalej.
Po większej migracji użyj crawlera i porównaj listę starych adresów z mapą przekierowań.
Najczęstsze błędy
Reguła zawiera ukośnik na początku wzorca
W .htaccess wzorzec RewriteRule jest dopasowywany względem bieżącego katalogu i zwykle nie zaczyna się od /.
Źle:
RewriteRule ^/stara/$ /nowa/ [R=301,L]
Poprawnie dla pliku w katalogu głównym:
RewriteRule ^stara/?$ /nowa/ [R=301,L]
Wszystkie stare adresy prowadzą na stronę główną
To słabe doświadczenie użytkownika i nie przekazuje mu właściwej odpowiedzi. Kieruj do najbliższego odpowiednika albo pozostaw prawidłowy błąd, jeśli odpowiednika nie ma.
Powstaje pętla
Najczęstsze przyczyny:
- HTTPS jest wymuszany jednocześnie przez hosting, CDN, wtyczkę i
.htaccess; - jedna warstwa wymusza
www, a druga usuwawww; - warunek pasuje również do adresu docelowego;
- serwer za proxy błędnie rozpoznaje protokół użytkownika.
Najpierw ustal, która warstwa ma być jedynym źródłem przekierowania kanonicznego.
Reguła działa dla zbyt wielu adresów
Wzorce bez ^ i $ mogą dopasować fragmenty, których nie planowano. Zaczynaj od możliwie precyzyjnego warunku, a regułę ogólną dodawaj dopiero po testach.
Zmiana jest zapisana w złym katalogu
Hosting może obsługiwać kilka domen w różnych katalogach. Upewnij się, że edytujesz .htaccess przypisany do właściwego katalogu dokumentów domeny.
Test kończy się na pierwszym 301
Sam fakt zwrócenia 301 nie oznacza sukcesu. Adres docelowy może zwrócić 404, kolejne 301 albo pętlę. Zawsze testuj cały łańcuch.
Checklista po wdrożeniu
- ☐ Źródłowy URL zwraca oczekiwany kod 301 lub tymczasowy kod 302/307.
- ☐ Nagłówek
Locationprowadzi bezpośrednio do ostatecznej wersji adresu. - ☐ Docelowy URL zwraca 200.
- ☐ Nie ma pętli ani zbędnego łańcucha.
- ☐ Zachowane są potrzebne fragmenty ścieżki i parametry.
- ☐ Warianty HTTP/HTTPS i
wwwnie tworzą dodatkowych niespodzianek. - ☐ Formularze i żądania POST nie są przekierowywane przypadkową regułą.
- ☐ Mapa XML i linki wewnętrzne wskazują już adres docelowy, a nie liczą na 301.
- ☐ Po migracji zaktualizowano adresy w Search Console i narzędziach analitycznych, jeśli było to potrzebne.
- ☐ Kopia poprzedniego
.htaccesspozostaje dostępna poza serwerem.
Podsumowanie
Najprostsze przekierowanie nie wymaga skomplikowanego wyrażenia regularnego. Użyj Redirect 301 dla jednego, trwałego przeniesienia. Sięgaj po RewriteRule dopiero wtedy, gdy potrzebujesz warunku lub wzorca. W WordPressie trzymaj własne reguły poza automatycznym blokiem i testuj cały łańcuch odpowiedzi, nie tylko zmianę adresu w przeglądarce.
Jeśli zmiana dotyczy całej domeny, dużej migracji, proxy/CDN-u albo działającego sklepu i formularzy, przygotuj mapę adresów oraz środowisko testowe. W takich przypadkach jedna „uniwersalna” reguła z internetu może kosztować więcej niż kontrolowane wdrożenie.
Potrzebujesz ustawić przekierowania, naprawić pętlę albo bezpiecznie przenieść stronę? Zobacz zakres wsparcia technicznego.