„Ładne linki” to często poszukiwany temat, ale rzadko jest on w pełni wyjaśniony. mod_rewrite to jeden ze sposobów tworzenia „ładnych linków”, ale jest złożony, a jego składnia jest bardzo zwięzła, trudna do zrozumienia, a dokumentacja zakłada pewien poziom biegłości w HTTP. Czy ktoś może w prosty sposób wyjaśnić, jak działają „ładne linki” i jak można użyć mod_rewrite do ich tworzenia?
Inne popularne nazwy, aliasy, terminy dotyczące czystych adresów URL: adresy URL zgodne z REST, adresy URL przyjazne dla użytkownika, adresy URL przyjazne dla SEO, adresy URL typu slugging i MVC (prawdopodobnie błędna nazwa)
apache
.htaccess
mod-rewrite
friendly-url
zamrozić
źródło
źródło
reference-mod-rewrite-url-rewriting-explained
samo jak ślimak,/questions/20563772/reference-mod-rewrite-url-rewriting-explained
to ładny adres URL..htaccess
imod-rewrite
powinny zostać zaktualizowane, aby zawierały link do tego pytania, ponieważ obejmuje on wiele z tego, co jest zadawane regularnie. Myśli?Odpowiedzi:
Aby zrozumieć, czym jest mod_rewrite, musisz najpierw zrozumieć, jak działa serwer WWW. Serwer WWW odpowiada na żądania HTTP . Żądanie HTTP na najbardziej podstawowym poziomie wygląda następująco:
Jest to proste żądanie przeglądarki skierowane do serwera WWW, które żąda od niego adresu URL
/foo/bar.html
. Ważne jest, aby podkreślić, że nie żąda pliku , żąda tylko jakiegoś dowolnego adresu URL. Żądanie może również wyglądać tak:Jest to równie ważne żądanie adresu URL, a bardziej oczywiste nie ma nic wspólnego z plikami.
Serwer WWW to aplikacja nasłuchująca na porcie, przyjmująca żądania HTTP przychodzące na tym porcie i zwracająca odpowiedź. Serwer WWW może odpowiadać na każde żądanie w dowolny sposób, jaki uzna za stosowny / w dowolny sposób, w jaki go skonfigurowałeś. Ta odpowiedź nie jest plikiem, jest odpowiedzią HTTP, która może, ale nie musi mieć nic wspólnego z fizycznymi plikami na dowolnym dysku. Serwer WWW nie musi być serwerem Apache, jest wiele innych serwerów WWW, które są po prostu programami działającymi trwale i podłączonymi do portu odpowiadającego na żądania HTTP. Możesz sam napisać. Ten akapit miał na celu oderwanie Cię od poglądu, że adresy URL są bezpośrednio równe plikom, co jest naprawdę ważne do zrozumienia. :)
Domyślna konfiguracja większości serwerów WWW polega na wyszukiwaniu pliku zgodnego z adresem URL na dysku twardym. Jeśli katalog główny serwera jest ustawiony na, powiedzmy,
/var/www
może sprawdzić, czy plik/var/www/foo/bar.html
istnieje i jeśli tak jest, może go obsłużyć. Jeśli plik kończy się na „.php”, wywoła interpreter PHP, a następnie zwróci wynik. Całe to powiązanie jest w pełni konfigurowalne; plik nie musi kończyć się rozszerzeniem „.php”, aby serwer WWW mógł go uruchomić przez interpreter PHP, a adres URL nie musi pasować do żadnego konkretnego pliku na dysku, aby coś się wydarzyło.mod_rewrite to sposób na przepisanie wewnętrznej obsługi żądań. Gdy serwer WWW otrzyma żądanie adresu URL
/foo/bar
, możesz przepisać ten adres URL na coś innego, zanim serwer WWW będzie szukał pliku na dysku, aby go dopasować. Prosty przykład:Ta reguła mówi, że za każdym razem , gdy żądanie pasuje do „/ foo / bar”, przepisz je do „/ foo / baz”. Żądanie będzie wówczas obsługiwane tak, jakby
/foo/baz
zamiast tego zostało poproszone. Można to wykorzystać do różnych efektów, na przykład:Ta reguła dopasowuje cokolwiek (
.*
) i przechwytuje to ((..)
), a następnie przepisuje, aby dodać „.html”. Innymi słowy, jeśli/foo/bar
żądany adres URL byłby obsługiwany tak, jakby/foo/bar.html
został poproszony. Widzieć http://regular-expressions.info, aby uzyskać więcej informacji na temat dopasowywania, przechwytywania i zastępowania wyrażeń regularnych.Inną często spotykaną zasadą jest:
To znowu dopasowuje wszystko i przepisuje go do pliku index.php z pierwotnie żądanym adresem URL dołączonym do
url
parametru zapytania. Oznacza to, że dla wszystkich przychodzących żądań wykonywany jest plik index.php i ten plik będzie miał dostęp do pierwotnego żądania w$_GET['url']
, dzięki czemu może zrobić z nim wszystko, co zechce.Przede wszystkim umieszczasz te reguły przepisywania w pliku konfiguracyjnym serwera WWW . Apache pozwala także * umieścić je w pliku o nazwie
.htaccess
w katalogu głównym twojego dokumentu (tj. Obok plików .php).* Jeśli pozwala na to podstawowy plik konfiguracyjny Apache; jest opcjonalny, ale często jest włączony.
Co mod_rewrite czy nie zrobić
mod_rewrite nie sprawia, że wszystkie adresy URL są „ładne”. To powszechne nieporozumienie. Jeśli masz to łącze w swojej witrynie internetowej:
mod_rewrite nie może nic zrobić, aby było to ładne. Aby był to ładny link, musisz:
Zmień link na ładny link:
Użyj mod_rewrite na serwerze, aby obsłużyć żądanie do adresu URL
/my/pretty/link
za pomocą jednej z metod opisanych powyżej.(Można go użyć
mod_substitute
w połączeniu do przekształcenia wychodzących stron HTML i zawartych w nich linków. Chociaż jest to zwykle więcej wysiłku niż tylko aktualizacja zasobów HTML.)Jest wiele możliwości mod_rewrite i bardzo złożone reguły dopasowywania, które możesz utworzyć, w tym łączenie kilku poprawek, przesyłanie żądań do zupełnie innej usługi lub maszyny, zwracanie określonych kodów stanu HTTP jako odpowiedzi, przekierowywanie żądań itp. Jest bardzo potężny i może być używany do świetnie, jeśli rozumiesz podstawowy mechanizm odpowiedzi na żądanie HTTP. Tak nie jest automatycznie dokonać linki ładna.
Zobacz oficjalną dokumentację dla wszystkich możliwych flag i opcji.
źródło
Aby rozwinąć odpowiedź deceze , chciałem podać kilka przykładów i wyjaśnić inne funkcje mod_rewrite.
RewriteEngine On
We wszystkich poniższych przykładach założono, że.htaccess
plik został już uwzględniony .Przepis na przykład
Weźmy ten przykład:
Reguła jest podzielona na 4 sekcje:
RewriteRule
- uruchamia regułę przepisywania^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$
- Nazywa się to wzorcem, ale będę nazywać go lewą stroną reguły - z czego chcesz przepisaćblog/index.php?id=$1&title=$2
- nazwał substytucję lub prawą stronę przepisywania reguły - do czego chcesz przepisać[NC,L,QSA]
są flagami dla reguły przepisywania, oddzielonymi przecinkiem, co wyjaśnię późniejPowyższe przepisanie pozwoliłoby na link do czegoś podobnego
/blog/1/foo/
i faktycznie by się załadowało/blog/index.php?id=1&title=foo
.Lewa strona reguły
^
wskazuje początek nazwy strony - więc zostanie przepisana,example.com/blog/...
ale nieexample.com/foo/blog/...
(…)
nawiasów reprezentuje wyrażenie regularne, które możemy przechwycić jako zmienną po prawej stronie reguły. W tym przykładzie:([0-9]+)
- odpowiada ciągowi o długości co najmniej 1 znaku i zawierającym tylko wartości liczbowe (tj. 0-9). Można się do tego odwołać za pomocą$1
po prawej stronie reguły-
lub+
(uwaga+
jest poprzedzona ukośnikiem odwrotnym, ponieważ bez zmiany jego znaczenia zostanie wykonana jako wyrażenie regularne znak powtórzenia ). Można się do tego odwołać za pomocą$2
po prawej stronie reguły?
oznacza, że poprzedni znak jest opcjonalny, więc w tym przypadku oba/blog/1/foo/
i/blog/1/foo
przepisałyby w to samo miejsce$
wskazuje, że jest to koniec ciągu, który chcemy dopasowaćFlagi
Są to opcje, które są dodawane w nawiasach kwadratowych na końcu reguły przepisywania, aby określić pewne warunki. Ponownie, istnieje wiele różnych flag, o których możesz przeczytać w dokumentacji , ale omówię niektóre z bardziej powszechnych flag:
Flaga no case oznacza, że w regule przepisywania nie jest rozróżniana wielkość liter, więc w przypadku powyższej reguły przykładowej oznaczałoby to, że zarówno
/blog/1/foo/
i/BLOG/1/foo/
(lub jakakolwiek ich odmiana) zostaną dopasowane.Ostatnia flaga wskazuje, że jest to ostatnia reguła, która powinna zostać przetworzona. Oznacza to, że wtedy i tylko wtedy, gdy ta reguła będzie pasować, żadne dalsze reguły nie będą oceniane w bieżącym przebiegu przetwarzania przepisywania. Jeśli reguła nie pasuje, wszystkie inne reguły zostaną wypróbowane w zwykłej kolejności. Jeśli nie ustawisz
L
flagi, wszystkie poniższe reguły zostaną później zastosowane do przepisanego adresu URL.Od Apache 2.4 możesz także używać
[END]
flagi. Pasująca reguła całkowicie zakończy dalsze przetwarzanie aliasów / przepisywania. (Podczas gdy[L]
flaga może często wywołać drugą rundę, na przykład podczas przepisywania do lub z podkatalogów).Flaga dołączania ciągu zapytania pozwala nam przekazać dodatkowe zmienne do określonego adresu URL, które zostaną dodane do oryginalnych parametrów get. W naszym przykładzie oznacza to, że coś takiego
/blog/1/foo/?comments=15
zostanie załadowane/blog/index.php?id=1&title=foo&comments=15
Ta flaga nie jest tą, której użyłem w powyższym przykładzie, ale uważam, że warto o niej wspomnieć. Pozwala to na określenie przekierowania http z opcją dołączenia kodu statusu (np
R=301
.). Na przykład, jeśli chcesz wykonać przekierowanie 301 na / myblog / to / blog /, po prostu napisz regułę mniej więcej taką:Przepisz warunki
Warunki ponownego zapisu sprawiają, że przepisywanie jest jeszcze bardziej wydajne, umożliwiając określenie przepisywania dla bardziej konkretnych sytuacji. Istnieje wiele warunków, o których możesz przeczytać w dokumentacji , ale przytoczę kilka typowych przykładów i wyjaśnię je:
Jest to bardzo powszechna praktyka polegająca na dodaniu Twojej domeny przedrostkiem
www.
(jeśli jeszcze jej tam nie ma) i wykonaniu przekierowania 301. Na przykład załadowaniehttp://example.com/blog/
go przekieruje Cię dohttp://www.example.com/blog/
Jest to nieco mniej powszechne, ale jest dobrym przykładem reguły, która nie jest wykonywana, jeśli nazwa pliku to katalog lub plik istniejący na serwerze.
%{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
wykona przepisanie tylko dla plików z rozszerzeniem jpg, jpeg, gif lub png (bez rozróżniania wielkości liter).%{REQUEST_FILENAME} !-f
sprawdzi, czy plik istnieje na bieżącym serwerze i wykona przepisanie tylko wtedy, gdy tak się nie stanie%{REQUEST_FILENAME} !-d
sprawdzi, czy plik istnieje na bieżącym serwerze i wykona przepisanie tylko wtedy, gdy tak się nie stanieźródło
Bibliografia
Stack Overflow ma wiele innych świetnych zasobów na początek:
(pamiętaj, aby usunąć ukośnik w
^/
prefiksach wzorców do.htaccess
użycia).A nawet przyjazne dla nowicjuszy przeglądy wyrażeń regularnych:
Często używane symbole zastępcze
.*
dopasowuje wszystko, nawet pusty ciąg. Nie chcesz używać tego wzorca wszędzie, ale często w ostatniej regule awaryjnej.[^/]+
jest częściej używany do segmentów ścieżki. Pasuje do wszystkiego oprócz ukośnika.\d+
pasuje tylko do ciągów numerycznych.\w+
dopasowuje znaki alfanumeryczne. Jest to w zasadzie skrót[A-Za-z0-9_]
.[\w\-]+
dla segmentów ścieżki w stylu „slug”, używając liter, cyfr, myślników-
i_
[\w\-.,]+
dodaje kropki i przecinki. Wolę uciekający\-
myślnik w[…]
klasach.\.
oznacza dosłowny okres. W przeciwnym razie.
poza[…]
jest symbolem zastępczym dla dowolnego symbolu.Każdy z tych symboli zastępczych jest zwykle zawijany w
(…)
nawiasach jako grupa przechwytywania. A cały wzór często w^………$
markerach początek + koniec. Cytowanie „wzorców” jest opcjonalne.RewriteRules
Poniższe przykłady są skoncentrowane na PHP i są nieco bardziej przyrostowe, łatwiejsze do dostosowania w podobnych przypadkach. To tylko podsumowania, często zawierają linki do większej liczby odmian lub szczegółowych pytań i odpowiedzi.
Mapowanie statyczne
/contact
,/about
Skrócenie kilku nazw stron do wewnętrznych schematów plików jest najprostsze:
Identyfikatory liczbowe
/object/123
Wprowadzenie skrótów, takich jak
http://example.com/article/531
do istniejących skryptów PHP, jest również łatwe. Numeryczny symbol zastępczy można po prostu odwzorować na$_GET
parametr:Symbole zastępcze w stylu informacji o pracy
/article/with-some-title-slug
Możesz łatwo rozszerzyć tę regułę, aby umożliwić stosowanie
/article/title-string
symboli zastępczych:Zauważ, że twój skrypt musi być zdolny (lub dostosowany) do mapowania tych tytułów z powrotem na identyfikatory baz danych. Samo RewriteRules nie może tworzyć ani odgadywać informacji z powietrza.
Ślimaki z prefiksami numerycznymi
/readable/123-plus-title
Dlatego często zobaczysz mieszane
/article/529-title-slug
ścieżki używane w praktyce:Teraz możesz po prostu pominąć przekazywanie i
title=$2
tak, ponieważ twój skrypt i tak będzie zazwyczaj polegał na identyfikatorze bazy danych.-title-slug
Stała arbitralne URL dekoracji.Jednolitość z alternatywnymi listami
/foo/…
/bar/…
/baz/…
Jeśli masz podobne reguły dla wielu wirtualnych ścieżek stron, możesz je dopasować i kompaktować za pomocą
|
alternatywnych list. I znowu po prostu ponownie przypisz je do wewnętrznych parametrów GET:Możesz podzielić je na pojedyncze,
RewriteRule
jeśli stanie się to zbyt skomplikowane.Wysyłanie powiązanych adresów URL do różnych backendów
/date/SWITCH/backend
Bardziej praktycznym zastosowaniem list alternatywnych jest mapowanie ścieżek żądań do różnych skryptów. Na przykład, aby zapewnić jednolite adresy URL dla starszej i nowszej aplikacji internetowej na podstawie dat:
To po prostu ponownie mapuje posty z lat 2009-2011 do jednego skryptu, a wszystkie pozostałe lata niejawnie do innego programu obsługi. Zwróć uwagę na bardziej szczegółową regułę, która pojawia się jako pierwsza . Każdy skrypt może używać innych parametrów GET.
Inne ograniczniki niż tylko
/
ukośniki ścieżek/user-123-name
Najczęściej widzisz RewriteRules do symulacji struktury katalogów wirtualnych. Ale nie jesteś zmuszony być nietwórczy. Możesz również użyć
-
łączników do segmentacji lub struktury.W przypadku również wspólnego
/wiki:section:Page_Name
schematu:Czasami dobrze jest naprzemiennie
/
używać -delimiterów, a:
nawet.
według tej samej reguły. Lub ponownie użyj dwóch RewriteRules, aby zmapować warianty na różne skrypty.Opcjonalny końcowy
/
ukośnik/dir
=/dir/
Decydując się na ścieżki w stylu katalogu, możesz sprawić, by były osiągalne z wersją końcową i bez niej /
Teraz obsługuje zarówno
http://example.com/blog/123
i/blog/123/
. A/?$
podejście jest łatwe do dołączania na jakikolwiek inny RewriteRule.Elastyczne segmenty dla ścieżek wirtualnych
.*/.*/.*/.*
Większość reguł, z którymi się spotkasz, mapuje ograniczony zestaw
/…/
segmentów ścieżki zasobów do poszczególnych parametrów GET. Jednak niektóre skrypty obsługują zmienną liczbę opcji . Silnik wyrażeń regularnych Apache nie pozwala na opcjonalizację dowolnej ich liczby. Ale możesz łatwo samodzielnie rozszerzyć go na blok reguł:Jeśli potrzebujesz maksymalnie pięciu segmentów ścieżki, skopiuj ten schemat do pięciu reguł. Możesz oczywiście użyć bardziej konkretnego
[^/]+
symbolu zastępczego. Tutaj kolejność nie jest tak ważna, ponieważ żadna z nich nie pokrywa się. Zatem posiadanie najpierw najczęściej używanych ścieżek jest w porządku.Alternatywnie możesz użyć parametrów tablicowych PHP za pośrednictwem
?p[]=$1&p[]=$2&p[]=3
ciągu zapytania tutaj - jeśli twój skrypt po prostu woli je wstępnie podzielić. (Chociaż częściej używa się reguły catch-all i pozwala skryptowi samodzielnie rozwinąć segmenty poza REQUEST_URI).Zobacz też: Jak przekształcić segmenty ścieżki adresu URL w pary klucz-wartość ciągu zapytania?
Opcjonalne segmenty
prefix/opt?/.*
Typową odmianą jest stosowanie opcjonalnych przedrostków w regule. Zwykle ma to sens, jeśli masz statyczne ciągi lub bardziej ograniczone symbole zastępcze wokół:
Teraz bardziej złożony wzór
(?:/([^/])+)?
po prostu zawija grupę nieprzechwytywaną(?:…)
i sprawia, że jest opcjonalna)?
. Zawarty symbol zastępczy([^/]+)
byłby wzorcem zastępowania$2
, ale powinien być pusty, jeśli nie ma środkowej/…/
ścieżki.Uchwyć resztę
/prefix/123-capture/…/*/…whatever…
Jak powiedziano wcześniej, często nie chcesz zbyt ogólnych wzorców przepisywania. Warto jednak łączyć statyczne i szczegółowe porównania z
.*
czasami.Spowoduje to opcjonalizację wszelkich
/…/…/…
końcowych segmentów ścieżki. Co wtedy oczywiście wymaga skryptu obsługującego, aby je rozdzielić, i same parametry wyodrębnia zmienne (co jest tym, co robią frameworki „MVC” sieci Web ).Końcowe „rozszerzenia” plików
/old/path.HTML
Adresy URL tak naprawdę nie mają rozszerzeń plików. O to właśnie chodzi w tym całym odwołaniu (= adresy URL są wirtualnymi lokalizatorami, niekoniecznie bezpośrednim obrazem systemu plików). Jednak jeśli miał 1: 1 mapowanie plików przed, może spreparować prostszych zasad:
Inne typowe zastosowania to ponowne mapowanie przestarzałych
.html
ścieżek do nowszych.php
programów obsługi lub po prostu tworzenie aliasów nazw katalogów tylko dla pojedynczych (rzeczywistych / rzeczywistych) plików.Ping-Pong (przekierowuje i przepisuje jednocześnie)
/ugly.html
← →/pretty
Więc w pewnym momencie przepisujesz swoje strony HTML, aby zawierały tylko ładne linki, zgodnie z deceze . W międzyczasie nadal będziesz otrzymywać żądania dotyczące starych ścieżek, czasem nawet z zakładek. Aby obejść ten problem , możesz ping-pong przeglądarek wyświetlić / ustanowić nowe adresy URL.
Ta powszechna sztuczka polega na wysyłaniu przekierowania 30x / Location, gdy przychodzący adres URL jest zgodny z przestarzałym / brzydkim schematem nazewnictwa. Przeglądarki ponownie zażądają nowego / ładnego adresu URL, który jest następnie przepisywany (tylko wewnętrznie) do oryginalnej lub nowej lokalizacji.
Zwróć uwagę, że w tym przykładzie zastosowano
[END]
zamiast[L]
bezpiecznej zmiany. W przypadku starszych wersji Apache 2.2 możesz użyć innych obejść, oprócz zmiany przypisania parametrów ciągu zapytania, na przykład: Przekieruj brzydki na ładny adres URL, ponownie odwróć do brzydkiej ścieżki, bez nieskończonych pętliSpacje ␣we wzorach
/this+that+
Nie wygląda to zbyt ładnie na pasku adresu przeglądarki, ale możesz używać spacji w adresach URL. W przypadku wzorców przepisywania należy używać
\␣
spacji ze znakami ucieczki odwrotnym ukośnikiem . W przeciwnym razie po prostu"
zacytuj cały wzorzec lub podstawienie:Klienci serializują adresy URL ze spacjami
+
lub%20
dla nich. Jednak w RewriteRules są one interpretowane za pomocą literalnych znaków dla wszystkich względnych segmentów ścieżki.Częste duplikaty:
Catch-all dla centralnego skryptu dyspozytora / kontrolera frontowego
Który jest często używany przez frameworki PHP lub skrypty WebCMS / portal. Rzeczywisty podział ścieżki jest następnie obsługiwany w PHP przy użyciu
$_SERVER["REQUEST_URI"]
. Więc koncepcyjnie jest to prawie przeciwieństwo obsługi adresów URL „na mod_rewrite”. (FallBackResource
Zamiast tego użyj .)Usunąć
www.
z nazwy hostaZwróć uwagę, że nie powoduje to skopiowania ciągu zapytania itp.
Zobacz też:
· Przepisywanie adresów URL dla różnych protokołów w .htaccess
· Ogólne przekierowanie htaccess z www na inny niż www
· .htaccess - jak wymusić "www". w ogólny sposób?
Zauważ, że kombinacje RewriteCond / RewriteRule mogą być bardziej złożone, a dopasowania (
%1
i$1
) oddziałują w obu kierunkach nawet:Podręcznik Apache - wprowadzenie mod_rewrite , Copyright 2015 The Apache Software Foundation, AL-2.0
Przekierować do
HTTPS://
Zobacz też: https://wiki.apache.org/httpd/RewriteHTTPToHTTPS
„Usuwanie” rozszerzenia PHP
Zobacz też: Usuwanie rozszerzenia .php za pomocą mod_rewrite
Aliasowanie starych ścieżek .html do skryptów .php
Zobacz: http://httpd.apache.org/docs/2.4/rewrite/remapping.html#backward-compatibility
Przepisz z adresu URL, na przykład „/ page”, do skryptu, na przykład „/index.php/page”
Zobacz mod_rewrite, php i plik .htaccess
Przekieruj subdomenę do folderu
Zobacz Jak mogę uzyskać dostęp do htaccess (subdomeny)?
Powszechne
.htaccess
pułapkiTeraz weź to z przymrużeniem oka. Nie każdą radę można uogólnić na wszystkie konteksty. To tylko proste podsumowanie dobrze znanych i kilku nieoczywistych przeszkód:
Włącz
mod_rewrite
i.htaccess
Aby faktycznie używać RewriteRules w plikach konfiguracyjnych dla poszczególnych katalogów, musisz:
Sprawdź, czy serwer jest
AllowOverride All
włączony . W przeciwnym razie.htaccess
dyrektywy dla poszczególnych katalogów zostaną zignorowane, a RewriteRules nie będzie działać.Oczywiście masz
mod_rewrite
włączone whttpd.conf
sekcji modułów.Do każdej listy reguł dołącz ciąg
RewriteEngine On
jeszcze. Chociaż mod_rewrite jest niejawnie aktywny w sekcjach<VirtualHost>
i<Directory>
,.htaccess
pliki dla poszczególnych katalogów wymagają indywidualnego przywołania.Główny ukośnik
^/
nie pasujeNie powinieneś normalnie rozpoczynać
.htaccess
wzorców RewriteRule^/
:Jest to często widoczne w starych samouczkach. I było to poprawne dla starożytnych wersji Apache 1.x. Obecnie ścieżki żądań są dogodnie w pełni względne względem katalogu w
.htaccess
RewriteRules. Po prostu zostaw/
wyprowadzenie.· Pamiętaj jednak, że wiodący ukośnik jest nadal poprawny w
<VirtualHost>
sekcjach. Dlatego często widzisz, że jest to^/?
opcja dla parytetu reguł.· Lub jeśli
RewriteCond %{REQUEST_URI}
użyjesz, nadal będziesz pasował do wiodącej/
.· Zobacz także Webmaster.SE: Kiedy wiodący ukośnik (/) jest potrzebny we wzorcach mod_rewrite?
<IfModule *>
opakowania zniknęły!Prawdopodobnie widziałeś to na wielu przykładach:
<VirtualHost>
sekcjach - jeśli zostało połączone z inną opcją awaryjną, taką jak ScriptAliasMatch. (Ale nikt tego nigdy nie robi)..htaccess
zestawów reguł z wieloma projektami typu open source. Jest to po prostu przeznaczone do zastępowania i zachowuje domyślne działanie „brzydkich” adresów URL.Jednak zwykle nie chcesz tego w swoich własnych
.htaccess
plikach.500
błędom HTTP . To, co zwykle osiąga, to zaszczycanie użytkowników404
błędami HTTP . (Nie o wiele bardziej przyjazne dla użytkownika, jeśli się nad tym zastanowić).Nie używaj,
RewriteBase
jeśli nie jest to potrzebneWiele przykładów kopiuj + wklej zawiera
RewriteBase /
dyrektywę. Co i tak jest domyślną wartością domyślną. Więc tak naprawdę tego nie potrzebujesz. Jest to obejście dla wymyślnych schematów przepisywania VirtualHost i błędnych ścieżek DOCUMENT_ROOT dla niektórych współdzielonych hostów.Warto używać z poszczególnymi aplikacjami internetowymi w głębszych podkatalogach. W takich przypadkach może skrócić wzorce RewriteRule. Ogólnie najlepiej jest preferować względne specyfikatory ścieżek w zestawach reguł dla poszczególnych katalogów.
Zobacz także Jak działa RewriteBase w .htaccess
Wyłącz,
MultiViews
gdy ścieżki wirtualne nakładają sięPrzepisywanie adresów URL jest używane głównie do obsługi wirtualnych ścieżek przychodzących. Zwykle wystarczy jeden dyspozytora skrypt (
index.php
) lub kilka pojedynczych teleskopowe (articles.php
,blog.php
,wiki.php
, ...). Ta ostatnia może kolidować z podobnymi wirtualnymi ścieżkami RewriteRule.Na
/article/123
przykład żądanie może być mapowane niejawnie doarticle.php
z/123
PATH_INFO. Wtedy albo musiałbyś strzec swoich reguł za pomocą zwykłegoRewriteCond
!-f
+!-d
i / lub wyłączyć obsługę PATH_INFO, albo po prostu wyłączyćOptions -MultiViews
.Co nie znaczy, że zawsze musisz . Negocjacje treści to po prostu automatyzm wirtualnych zasobów.
Kolejność jest ważna
Zobacz wszystko, co kiedykolwiek chciałeś wiedzieć o mod_rewrite, jeśli jeszcze tego nie zrobiłeś. Łączenie wielu reguł RewriteRules często prowadzi do interakcji. To nie jest coś, co zwykle należy zapobiegać za
[L]
flagę, ale schemat, który przyjmiesz po zapoznaniu się. Państwo może re-re-re zapisu wirtualnych ścieżek z jednej reguły do drugiego, aż osiągnie rzeczywistą obsługi docelowej.Mimo to często chciałbyś mieć najbardziej szczegółowe reguły (ustalone
/forum/…
wzorce ciągów lub bardziej restrykcyjne symbole zastępcze[^/.]+
) we wczesnych regułach. Ogólne reguły slurp-all (.*
) lepiej zostawić późniejszym . (Wyjątkiem jestRewriteCond -f/-d
strażnik jako główny blok).Arkusze stylów i obrazy przestają działać
Wprowadzenie struktur katalogów wirtualnych ma
/blog/article/123
wpływ na względne odwołania do zasobów w języku HTML (na przykład<img src=mouse.png>
). Które można rozwiązać:href="https://stackoverflow.com/old.html"
lubsrc="/logo.png"
<base href="https://stackoverflow.com/index">
do<head>
sekcji HTML . To niejawnie zmienia względne odniesienia do tego, czym były wcześniej.Możesz alternatywnie stworzyć dalsze Reguły RewriteRules, aby zmienić powiązanie
.css
lub.png
ścieżki do ich pierwotnych lokalizacji. Ale to jest zarówno niepotrzebne, jak i powoduje dodatkowe przekierowania i utrudnia buforowanie.Zobacz też: CSS, JS i obrazy nie wyświetlają się z ładnym adresem URL
RewriteConds tylko maskuje jedną RewriteRule
Częstym błędem jest to, że RewriteCond blokuje wiele Reguł RewriteRules (ponieważ są one wizualnie ułożone razem):
Które nie jest domyślnie. Możesz je połączyć za pomocą
[S=2]
flagi. W przeciwnym razie będziesz musiał je powtórzyć. Chociaż czasami można utworzyć „odwróconą” regułę podstawową, aby [END] przerabiać przetwarzanie wcześniej.QUERY_STRING zwolnione z RewriteRules
Nie możesz dopasować
RewriteRule index.php\?x=y
, ponieważ mod_rewrite porównuje domyślnie tylko ze ścieżkami względnymi. Możesz jednak dopasować je osobno poprzez:Zobacz także Jak mogę dopasować zmienne ciągu zapytania do mod_rewrite?
.htaccess
vs.<VirtualHost>
Jeśli używasz RewriteRules w pliku konfiguracyjnym dla każdego katalogu, martwienie się o wydajność wyrażeń regularnych jest bezcelowe. Apache zachowuje skompilowane wzorce PCRE dłużej niż proces PHP ze wspólną strukturą routingu. W przypadku witryn o dużym natężeniu ruchu należy jednak rozważyć przeniesienie zestawów reguł do konfiguracji serwera vhost, gdy zostaną przetestowane w walce.
W takim przypadku preferuj opcjonalny
^/?
prefiks separatora katalogów. Pozwala to na swobodne przenoszenie RewriteRules między plikami konfiguracyjnymi PerDir i serwera.Zawsze, gdy coś nie działa
Nie denerwować.
Porównaj
access.log
ierror.log
Często można dowiedzieć się, w jaki sposób reguła RewriteRule zachowuje się nieprawidłowo, patrząc na Twoje
error.log
iaccess.log
. Skoreluj czasy dostępu, aby zobaczyć, która ścieżka żądań pierwotnie nadeszła i której ścieżki / pliku Apache nie mógł rozwiązać (błąd 404/500).To nie mówi ci, która RewriteRule jest winowajcą. Ale niedostępne ścieżki końcowe, takie jak,
/docroot/21-.itle?index.php
mogą zdradzić, gdzie można dalej zbadać. W przeciwnym razie wyłącz reguły, dopóki nie uzyskasz przewidywalnych ścieżek.Włącz RewriteLog
Zobacz dokumentację Apache RewriteLog . Do debugowania możesz włączyć to w sekcjach vhost:
Daje to szczegółowe podsumowanie tego, jak ścieżki żądań przychodzących są modyfikowane przez każdą regułę:
Co pomaga zawęzić zbyt ogólne reguły i wpadki w wyrażeniach regularnych.
Zobacz też:
· .htaccess nie działa (mod_rewrite)
· Wskazówki dotyczące debugowania .htaccess zasady przepisywania
Zanim zadasz własne pytanie
Jak być może wiesz, przepełnienie stosu bardzo dobrze nadaje się do zadawania pytań na temat mod_rewrite. Niech będą na temat , uwzględniając wcześniejsze badania i próby (unikaj zbędnych odpowiedzi), zademonstruj podstawowewyrażenie regularne zrozumienie i:
$_SERVER
środowisko PHP, jeśli chodzi o niezgodność parametrów.access.log
ierror.log
weryfikacja, na co rozwiązały się istniejące przepisy. Jeszcze lepiej,rewrite.log
podsumowanie.Zapewnia to szybsze i dokładniejsze odpowiedzi oraz sprawia, że są one bardziej przydatne dla innych.
Skomentuj swój
.htaccess
Jeśli kopiujesz skądś przykłady, pamiętaj o dołączeniu pliku
# comment and origin link
. Chociaż pomijanie atrybucji jest tylko złymi manierami, często naprawdę szkodzi późniejszej konserwacji. Dokumentuj dowolny kod lub źródło samouczka. W szczególności, gdy nie masz odwrotu, tym bardziej powinieneś być zainteresowany traktowaniem ich jak magicznych czarnych skrzynek.To nie są adresy URL „SEO”
Zastrzeżenie: tylko irytujące zwierzę. Często słyszysz ładne schematy przepisywania adresów URL, nazywane linkami „SEO” lub czymś podobnym. Chociaż jest to przydatne przy wyszukiwaniu przykładów w Google, jest to przestarzała myląca nazwa.
Żaden ze współczesnych wyszukiwarek są naprawdę przeszkadzał
.html
i.php
w segmentach Ścieżka lub?id=123
ciągów zapytań dotyczących tej sprawy. Wyszukiwarki starych, takich jak AltaVista, zrobił Unikaj indeksowania stron internetowych z potencjalnie niejednoznaczną ścieżek dostępu. Nowoczesne roboty często pragną nawet zasobów głębokiej sieci.Koncepcyjnie należy używać „ładnych” adresów URL, aby uczynić witryny przyjaznymi dla użytkownika .
/common/tree/nesting
.Jednak nie rezygnuj z wyjątkowych wymagań dla konformizmu.
Przybory
Istnieją różne narzędzia online do generowania reguł RewriteRules dla większości adresów URL z parametrami GET:
Przeważnie wyświetla tylko
[^/]+
ogólne symbole zastępcze, ale prawdopodobnie wystarcza w przypadku trywialnych witryn.źródło
Alternatywy dla mod_rewrite
Wiele podstawowych schematów wirtualnych adresów URL można osiągnąć bez korzystania z RewriteRules. Apache pozwala na wywoływanie skryptów PHP bez
.php
rozszerzenia iz wirtualnymPATH_INFO
argumentem.Użyj PATH_INFO , Luke
Obecnie
AcceptPathInfo On
jest często domyślnie włączona. Co w zasadzie pozwala.php
i innym adresom URL zasobów na przenoszenie wirtualnego argumentu:Teraz
/virtual/path
pojawia się to w PHP,$_SERVER["PATH_INFO"]
gdzie możesz obsłużyć dodatkowe argumenty, jak chcesz.Nie jest to wygodne, jak o Apache oddzielne segmenty ścieżki danych wejściowych
$1
,$2
,$3
i przekazywać je w różnych$_GET
zmiennych do php. Po prostu emuluje „ładne adresy URL” przy mniejszym wysiłku konfiguracyjnym.Włącz MultiViews, aby ukryć
.php
rozszerzenieNajprostszą opcją unikania
.php
„rozszerzeń plików” w adresach URL jest włączenie:Powoduje to
article.php
włączenie funkcji wyboru Apache dla żądań HTTP/article
ze względu na pasującą nazwę basenową. Działa to dobrze w połączeniu z wyżej wspomnianą funkcją PATH_INFO. Możesz więc po prostu użyć adresów URL, takich jakhttp://example.com/article/virtual/title
. Ma to sens, jeśli masz tradycyjną aplikację internetową z wieloma punktami / skryptami wywołań PHP.Pamiętaj jednak, że MultiViews ma inny / szerszy cel. Wiąże się to z bardzo niewielkim spadkiem wydajności, ponieważ Apache zawsze szuka innych plików z pasującymi nazwami basenowymi. To rzeczywiście przeznaczona dla Content-negocjacja , więc przeglądarek otrzymać najlepszą alternatywę wśród dostępnych zasobów (takich jak
article.en.php
,article.fr.php
,article.jp.mp4
).SetType lub SetHandler dla
.php
skryptów bez rozszerzeńBardziej ukierunkowanym podejściem do uniknięcia przenoszenia
.php
sufiksów w adresach URL jest skonfigurowanie programu obsługi PHP dla innych schematów plików. Najprostszą opcją jest zastąpienie domyślnego typu MIME / obsługi poprzez.htaccess
:W ten sposób możesz po prostu zmienić nazwę swojego
article.php
skryptu na po prostuarticle
(bez rozszerzenia), ale nadal przetwarzać go jako skrypt PHP.Może to mieć pewne konsekwencje dla bezpieczeństwa i wydajności, ponieważ wszystkie pliki bez rozszerzeń będą teraz przesyłane potokiem przez PHP. Dlatego możesz alternatywnie ustawić to zachowanie tylko dla pojedynczych plików:
Jest to w pewnym stopniu zależne od konfiguracji serwera i używanego PHP SAPI. Typowe alternatywy obejmują
ForceType application/x-httpd-php
lubAddHandler php5-script
.Inne schematy przepisywania Apache
Wśród wielu opcji Apache zapewnia
mod_alias
funkcje - które czasami działają równie dobrze jakmod_rewrite
RewriteRules. Zauważ, że większość z nich musi być skonfigurowana w<VirtualHost>
sekcji, ale nie w.htaccess
plikach konfiguracyjnych poszczególnych katalogów.ScriptAliasMatch
jest przeznaczony głównie dla skryptów CGI, ale powinien również działać dla PHP. Pozwala na wyrażenia regularne, takie jak inneRewriteRule
. W rzeczywistości jest to prawdopodobnie najbardziej niezawodna opcja konfiguracji kontrolera frontowego typu catch-all.A zwykły
Alias
pomaga również w kilku prostych schematach przepisywania.Nawet zwykła
ErrorDocument
dyrektywa mogłaby zostać użyta, aby pozwolić skryptowi PHP obsługiwać ścieżki wirtualne. Zauważ, że jest to niezgrabne obejście, jednak zabrania czegokolwiek poza żądaniami GET i z definicji przepełnia error.log.Więcej wskazówek można znaleźć pod adresem http://httpd.apache.org/docs/2.2/urlmapping.html .
źródło