Przekierowanie 301 w .htaccess to jedna linia:
Redirect 301 /old-page https://example.com/new-page
Zapisz to w pliku .htaccess w katalogu głównym dokumentów i działa to natychmiast. Apache czyta plik przy każdym zapytaniu, więc nie ma restartu i nie ma deployu. Dyrektywa pochodzi z mod_alias, obecnego praktycznie w każdej instalacji Apache, i wysyła 301 Moved Permanently z nagłówkiem Location. To cała robota.
Prawie wszystko, co idzie źle w przekierowaniach Apache, dzieje się po tym punkcie: sięganie po RewriteRule, gdy wystarczyłby Redirect, mieszanie obu modułów w jednym pliku i otrzymanie kolejności, jakiej nikt się nie spodziewał, albo utrata parametrów zapytania w drodze. Ten artykuł omawia cztery reguły warte zapamiętania, pułapkę kolejności wykonania, która sprawia, że poprawnie wyglądające pliki zachowują się źle, oraz sposób na przetestowanie przekierowania bez okłamywania cię przez przeglądarkę. Po szerszy obraz tego, gdzie mogą żyć przekierowania, zobacz jak przekierować URL.
Jedna linia, która obejmuje większość przekierowań
Redirect przyjmuje status, ścieżkę do dopasowania i cel. Cel może być pełnym URL-em albo ścieżką na tym samym hoście:
Redirect 301 /old-page /new-page
Redirect 301 /shop https://shop.example.com/
RedirectMatch 301 ^/blog/([0-9]{4})/(.*)$ /articles/$2
Dwa zachowania warto znać, zanim go użyjesz. Po pierwsze, własne wytyczne Apache wyraźnie mówią, że to jest właściwe narzędzie: "Ten rodzaj prostego przekierowania jednego URL-a, albo klasy URL-i, gdzie indziej, powinien być realizowany za pomocą tych dyrektyw, a nie RewriteRule."
Po drugie, i to zaskakuje ludzi: "Pamiętaj, że Redirect zachowuje informację o ścieżce. To znaczy, że przekierowanie dla URL-a /one przekieruje też wszystkie URL-e pod nim, takie jak /one/two.html i /one/three/four.html." Jeśli chcesz tylko dokładnej ścieżki, RedirectMatch 301 ^/one$ zakotwicza ją. W przeciwnym razie właśnie przekierowałeś całe poddrzewo, co czasem jest dokładnie tym, czego chciałeś, a czasem bardzo mylącym porankiem.
RedirectMatch to wersja z wyrażeniami regularnymi i obejmuje większość tego, po co ludzie otwierają mod_rewrite. Przechwycone grupy trafiają do $1, $2 i tak dalej, więc zmiana nazwy katalogu albo zmiana schematu URL-i opartego na dacie to jednolinijkowiec.
Kiedy naprawdę potrzebujesz RewriteRule
Sięgnij po mod_rewrite, gdy decyzja zależy od czegoś innego niż ścieżka. Host, parametry zapytania, metoda żądania, cookies i user agent są wszystkie widoczne dla RewriteCond i niewidoczne dla Redirect:
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)ref=oldpartner(&|$)
RewriteRule ^landing$ /partners/oldpartner? [R=301,L]
Jest jedna pułapka w kontekście per-directory, która odpowiada za ogromną część skopiowanych reguł, które nic nie robią. Apache usuwa prefiks katalogu przed dopasowaniem, więc wzorzec nigdy nie widzi ukośnika na początku: "Usunięty prefiks zawsze kończy się ukośnikiem, co znaczy, że dopasowanie zachodzi wobec ciągu, który nigdy nie ma ukośnika na początku. Dlatego wzorzec z ^/ nigdy nie dopasowuje się w kontekście per-directory."
Dlatego RewriteRule ^/old$ /new [R=301] działa, gdy ktoś wklei to do virtual hosta, i po cichu zawodzi w .htaccess. Usuń ukośnik: ^old$. Kiedy twoje podstawienie jest ścieżką względną a przepisanie żyje w podkatalogu, może być też potrzebny RewriteBase, żeby powiedzieć Apache, względem czego są te ścieżki.
Pułapka kolejności wykonania
To jest ta, która kosztuje ludzi popołudnie. Pozycja linii w pliku nie decyduje, który moduł działa pierwszy.
Apache dokumentuje to wprost: "Jeśli mieszasz Redirect i RewriteRule w tym samym kontekście, miej na uwadze, że ich kolejność wykonania zależy od miejsca, w którym się pojawiają. W kontekście serwera/virtual-host, mod_rewrite działa pierwszy; w kontekście per-directory (.htaccess), mod_alias działa pierwszy."
Przeczytaj to dwa razy, bo konsekwencja jest sprzeczna z intuicją. W pliku .htaccess Redirect na dole pliku bije RewriteRule na górze. Przenieś identyczne reguły do virtual hosta, a zwycięzca się odwraca. Flaga [L] też cię nie uratuje: znaczy ona ostatnia reguła w tym przebiegu mod_rewrite, nie ostatnia reguła w pliku, i nie ma żadnej władzy nad innym modułem.
Praktyczna reguła, którą się kieruję: jeden moduł na plik. Jeśli projekt gdziekolwiek potrzebuje warunków, zrób wszystkie jego przekierowania za pomocą mod_rewrite i usuń linie Redirect. Z mieszanych plików pochodzą zgłoszenia błędów w stylu "przekierowanie działa na staging, ale nie na produkcji", bo te dwa środowiska umieszczają reguły w różnych kontekstach.
Parametry zapytania: zachowane, zastąpione albo usunięte
Linki marketingowe żyją i umierają przez swoje parametry zapytania, więc ta tabela jest warta przypięcia. Wszystko to jest udokumentowanym zachowaniem, a nie folklorem.
| Co piszesz | Oryginalne parametry zapytania | Uwagi |
|---|---|---|
Redirect 301 /a /b | Przenoszone dalej | mod_alias dołącza je za tobą |
RedirectMatch 301 ^/a$ /b | Przenoszone dalej | Ten sam moduł, to samo zachowanie |
RewriteRule ^a$ /b [R=301] | Przechodzą bez zmian | Udokumentowane ustawienie domyślne |
RewriteRule ^a$ /b?src=x [R=301] | Zastąpione twoimi | Twoje parametry wygrywają |
RewriteRule ^a$ /b?src=x [R=301,QSA] | Połączone z twoimi | QSA dołącza oryginalne |
RewriteRule ^a$ /b? [R=301] | Usunięte | Sam ? je czyści |
Sformułowanie Apache o domyślnym zachowaniu: "Domyślnie parametry zapytania przechodzą bez zmian." A co do flag, [QSA] "dołącza wszelkie parametry zapytania z oryginalnego URL-a żądania do wszelkich parametrów zapytania utworzonych w celu przepisania", podczas gdy [QSD] odrzuca przychodzące. Jeśli przekierowujesz do absolutnego URI, parametry zapytania idą razem z nim, o ile nie poprosisz o [QSD].
Awaria, której to zapobiega, jest cicha i kosztowna. Reguła, która zastępuje parametry zapytania, usuwa utm_source i utm_campaign w drodze, twoja analityka przypisuje sesję do ruchu bezpośredniego, i nic się nie wysypuje. Nikt tego nie zauważa, aż ktoś zapyta, czemu wiosenna kampania nie dostała żadnego uznania. Parametry UTM nie pojawiają się w GA4 omawia diagnozę ze strony analityki.
Jeśli zauważasz, że utrzymujesz dziesiątki przekierowań kampanijnych w pliku konfiguracji serwera, to jest sygnał, a nie tylko obowiązek. Reguły serwerowe potrzebują deployu, przeglądu konfiguracji Apache i kogoś z dostępem do shella. Przenieś linki kampanijne na krótkie linki, które możesz edytować samodzielnie i zostaw .htaccess dla przekierowań strukturalnych, w których jest dobry.
HTTPS i www w jednym skoku, nie w dwóch
Najczęściej kopiowany fragment kodu w internecie robi to w dwóch blokach reguł, co znaczy, że odwiedzający przychodzący na http://example.com/page zostaje przekierowany dwa razy: raz, żeby dodać TLS, raz, żeby dodać www. Dwa skoki, dwa round tripy, i lekko słabszy sygnał przy każdym z nich.
Jedna reguła, dwa warunki, jeden skok:
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]
Za CDN albo load balancerem, %{HTTPS} jest zwykle off na originie, nawet gdy odwiedzający jest na HTTPS, bo TLS zakończył się wcześniej. Testuj za to %{HTTP:X-Forwarded-Proto}:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
Pomyl to, i zbudujesz nieskończoną pętlę przekierowań: proxy wysyła HTTPS, origin myśli, że to HTTP, przekierowuje na HTTPS, i tak w kółko, aż przeglądarka się poddaje. Jak naprawić pętlę przekierowań opisuje diagnozowanie tego z nagłówków odpowiedzi.
Czemu to nie działa
W kolejności, w jakiej je sprawdzam:
AllowOverridejest ustawione naNone. Dokumentacja Apache podaje ustawienie domyślne: "To znaczy, że pliki.htaccesssą całkowicie ignorowane, o ile nie włączysz ich wyraźnie dla katalogu." Sprawdź to, umieszczając celowy bełkot w pierwszej linii. Brak błędu 500 znaczy, że twój plik w ogóle nie jest czytany, a każda reguła w nim jest dekoracją.- Plik jest w złym miejscu albo źle nazwany. Musi być
.htaccess, z wiodącą kropką, w katalogu, na który mapuje się żądanie. Edytory, które usłużnie zapisująhtaccess.txt, to powracająca przyczyna. - mod_rewrite nie jest wczytany.
Redirectdziała,RewriteRulepo cichu nie, co wysyła ludzi na godzinę wpatrywania się we własne wyrażenie regularne. - Twoja przeglądarka zapamiętała starą 301. Chrome i Firefox obie agresywnie cache'ują trwałe przekierowania, per profil przeglądarki, więc poprawka, którą właśnie wdrożyłeś, jest dla ciebie niewidoczna, a dla wszystkich innych działa dobrze. W trakcie developmentu używaj
R=302i przełącz naR=301, gdy reguła jest poprawna. - Reguła trafia we własny cel.
RewriteRule ^(.*)$ /index.php/$1bez zabezpieczenia to klasyk. Dodaj warunek, który wyłącza cel.
Testuj curl-em, nie przeglądarką
Jedna komenda mówi ci status, cel i ile skoków to zajęło:
curl -sIL https://example.com/old-page | grep -iE '^HTTP|^location'
Czytaj wynik jako sekwencję. Dwie linie HTTP/2 301 przed 200 znaczą dwa skoki, a każdy skok to prawdziwy round trip dla prawdziwego odwiedzającego w sieci mobilnej. Dokumentacja Google o przekierowaniach traktuje trwałe przekierowanie jako najsilniejszy sygnał do konsolidacji URL-a, a dotarcie tam w jednym kroku jest ściśle lepsze niż dotarcie w trzech. Nasz link checker wypisuje ten sam łańcuch w przeglądarce, a przekierowania 301 kontra 302 omawia, który status wysłać, gdy nie jesteś pewien.
Testuj ścieżki, które mają znaczenie, a nie tylko tę, którą właśnie napisałeś: root, głęboką ścieżkę, ścieżkę z parametrami zapytania i sam cel. Ten ostatni wychwytuje pętle, zanim zrobią to twoi odwiedzający.
Kiedy w ogóle nie używać .htaccess
Własne stanowisko Apache jest jednoznaczne. "Jeśli masz dostęp do głównego pliku konfiguracji serwera, powinieneś umieścić tam całą swoją konfigurację, a nie w plikach .htaccess," bo parsowanie przy każdym żądaniu kosztuje realną pracę: "dopuszczenie plików .htaccess powoduje spadek wydajności, niezależnie od tego, czy faktycznie z nich korzystasz." Na hostingu współdzielonym nie masz wyboru. Na serwerze, który kontrolujesz, główna konfiguracja jest lepszym domem dla wszystkiego, co strukturalne.
Jest drugi powód, żeby całkowicie trzymać reguły poza plikiem, i nie ma to nic wspólnego z wydajnością. Przekierowania, które pojawiają się w druku, w kodzie QR albo na czyjejś prezentacji, muszą przeżyć twój serwer WWW, migrację CMS-a i możliwe zmianę dostawcy hostingu. Reguła w .htaccess jest jednym nieuważnym deployem od zniknięcia, i nikt nie zgłasza martwego wydrukowanego linku, aż kampania się skończy. Przekierowania strukturalne należą do serwera; linki kampanijne i drukowane należą gdzieś, gdzie możesz je edytować w kilka sekund i mierzyć bez grepowania logów dostępu.
Przeczytaj serię filarową
Ten artykuł należy do klastra tutoriali. Po pełną mapę, typy przekierowań omawia każdy kod statusu i metodę po stronie klienta, a jak przekierować URL omawia sześć miejsc, w których może żyć przekierowanie.
Powiązane na blogu
Najczęściej zadawane pytania
Jak stworzyć przekierowanie 301 w .htaccess?
Umieść jedną linię w pliku .htaccess w katalogu głównym dokumentów: Redirect 301 /old-page https://example.com/new-page. Apache czyta .htaccess przy każdym zapytaniu, więc przekierowanie działa w momencie zapisania pliku. Bez restartu, bez deployu. Ta dyrektywa pochodzi z mod_alias, który jest włączony praktycznie w każdej instalacji Apache.
Jaka jest różnica między Redirect i RewriteRule?
Redirect i RedirectMatch pochodzą z mod_alias i robią jedną rzecz: wysyłają kod statusu i nagłówek Location. RewriteRule pochodzi z mod_rewrite i może sprawdzić host, parametry zapytania, cookies albo user agenta, zanim podejmie decyzję. Własna dokumentacja Apache mówi, że proste przekierowania powinny używać mod_alias, a nie RewriteRule, i traktuje mod_rewrite jako ostatnią możliwość.
Czemu moje przekierowanie w .htaccess nie działa?
Pięć przyczyn obejmuje prawie wszystko: AllowOverride jest ustawione na None, więc plik jest całkowicie ignorowany, plik nie znajduje się w katalogu głównym dokumentów albo ma źle nazwę, mod_rewrite nie jest wczytany, twoja przeglądarka zapamiętała wcześniejsze 301 i już nigdy nie pyta serwera, albo reguła trafia we własny cel i zapętla się. Testuj curl-em, nie przeglądarką, bo zapamiętane 301 sprawia, że naprawiona reguła wygląda na zepsutą.
Czy parametry zapytania przetrwają przekierowanie 301 w .htaccess?
Z Redirect i RedirectMatch, tak, są przenoszone automatycznie. Z RewriteRule odpowiedź zależy od podstawienia: brak znaku zapytania w nim i oryginalne parametry przechodzą dalej, znak zapytania i twoje własne parametry je zastępują, sam znak zapytania na końcu je usuwa, a flaga QSA łączy oba. Pomylenie tego po cichu gubi parametry UTM.
Jak przekierować HTTP na HTTPS i non-www na www w jednym skoku?
Użyj jednej reguły z dwoma warunkami połączonymi przez OR, przepisując na kanoniczny schemat i host w jednym kroku. Dwa osobne bloki reguł tworzą dwa przekierowania dla każdego, kto przychodzi na http:// bez www, a każdy dodatkowy skok kosztuje opóźnienie i rozmywa sygnał. Za proxy albo CDN testuj %{HTTP:X-Forwarded-Proto} zamiast %{HTTPS}, inaczej zbudujesz pętlę.
Czy .htaccess zwalnia stronę?
Trochę, i nieuchronnie. Dokumentacja Apache jest w tej sprawie bezpośrednia: dopuszczenie plików .htaccess powoduje spadek wydajności niezależnie od tego, czy z nich korzystasz, bo httpd szuka pliku w każdym katalogu przy każdym zapytaniu. Jeśli masz dostęp do głównej konfiguracji serwera, te same reguły powinny być tam, wczytywane raz przy starcie.
Wypróbuj Elido
Wklej URL, otrzymaj krótki link
Bez rejestracji. Link działa 30 dni. Zarejestruj się, aby zachować go na zawsze.
Za darmo, bez rejestracji · 2 dziennie