Apache mod_rewrite
To czego szukasz to mod_rewrite ,
Opis: zapewnia mechanizm przepisywania oparty na regułach, który umożliwia natychmiastowe przepisywanie żądanych adresów URL.
Ogólnie rzecz biorąc, mod_rewrite
działa dopasowując żądany dokument do określonych wyrażeń regularnych, a następnie wykonuje przepisywanie adresu URL wewnętrznie (w ramach procesu apache) lub zewnętrznie (w przeglądarce klienta). Te przepisy mogą być tak proste, jak wewnętrzne przetłumaczenie example.com/foo na żądanie na przykład.com/foo/bar.
Dokumentacja Apache zawiera mod_rewrite
przewodnik i myślę, że niektóre z rzeczy, które chcesz zrobić, są w nim zawarte. Szczegółowy przewodnik po mod_rewrite .
Wymuś www
subdomenę
Chciałbym, aby wymuszał „www” przed każdym adresem URL, więc nie jest to domena.com, ale www.domena.com/strona
Przewodnik po przepisywaniu zawiera instrukcje dotyczące tego w przykładzie nazwy hosta kanonicznego .
Usuń końcowe ukośniki (część 1)
Chciałbym usunąć wszystkie końcowe ukośniki ze stron
Nie jestem pewien, dlaczego chcesz to zrobić, ponieważ przewodnik po przepisywaniu zawiera przykład dokładnie odwrotny , tj. Zawsze zawiera kończący ukośnik. Dokumenty sugerują, że usunięcie końcowego ukośnika może powodować problemy:
Problem z końcowym ukośnikiem
Opis:
Każdy webmaster może zaśpiewać piosenkę o problemie końcowego ukośnika w adresach URL odwołujących się do katalogów. Jeśli ich brakuje, serwer zrzuca błąd, ponieważ jeśli powiesz /~quux/foo
zamiast /~quux/foo/
tego, serwer wyszuka plik o nazwie foo. A ponieważ ten plik jest katalogiem, narzeka. W rzeczywistości w większości przypadków próbuje to naprawić samodzielnie, ale czasami ten mechanizm musi być przez Ciebie emulowany. Na przykład po wykonaniu wielu skomplikowanych przepisywania adresów URL na skrypty CGI itp.
Być może mógłbyś rozwinąć, dlaczego chcesz cały czas usuwać końcowy ukośnik?
Usuń .php
rozszerzenie
Potrzebuję go, aby usunąć plik .php
Najbliższą rzeczą, o której mogę pomyśleć, jest wewnętrzne przepisanie każdego dokumentu żądania z rozszerzeniem .php, tj. Przykład.com/somepage jest zamiast tego przetwarzany jako żądanie na przykład przyklad.com/somepage.php. Zauważ, że postępowanie w ten sposób wymagałoby, aby każda strona faktycznie istniała jako strona.php w systemie plików.
Przy odpowiedniej kombinacji wyrażeń regularnych powinno to być do pewnego stopnia możliwe. Mogę jednak przewidzieć pewne możliwe problemy związane z nieprawidłowym żądaniem stron indeksu i nieprawidłowym dopasowaniem katalogów.
Na przykład spowoduje to poprawne przepisanie example.com/test jako żądania na przykład.com/test.php:
RewriteEngine on
RewriteRule ^(.*)$ $1.php
Ale spowoduje, że example.com się nie załaduje, ponieważ nie ma example.com/.php
Zgaduję, że jeśli usuniesz wszystkie końcowe ukośniki, to wybranie żądania indeksu katalogu z żądania nazwy pliku w katalogu nadrzędnym stanie się prawie niemożliwe. Jak określić żądanie katalogu „foobar”:
example.com/foobar
z żądania pliku o nazwie foobar (który w rzeczywistości jest foobar.php)
example.com/foobar
Byłoby to możliwe, gdybyś użył RewriteBase
dyrektywy. Ale jeśli to zrobisz, problem stanie się znacznie bardziej skomplikowany, ponieważ będziesz wymagać RewriteCond
dyrektyw do sprawdzania na poziomie systemu plików, czy żądanie jest mapowane do katalogu lub pliku.
To powiedziawszy, jeśli usuniesz wymóg usunięcia wszystkich końcowych ukośników i zamiast tego wymuś dodawanie końcowych ukośników, problem „bez rozszerzenia .php” stanie się nieco bardziej rozsądny.
# Turn on the rewrite engine
RewriteEngine on
# If the request doesn't end in .php (Case insensitive) continue processing rules
RewriteCond %{REQUEST_URI} !\.php$ [NC]
# If the request doesn't end in a slash continue processing the rules
RewriteCond %{REQUEST_URI} [^/]$
# Rewrite the request with a .php extension. L means this is the 'Last' rule
RewriteRule ^(.*)$ $1.php [L]
To nadal nie jest idealne - każde żądanie dotyczące pliku nadal ma wewnętrznie dołączany plik .php. Żądanie „hi.txt” spowoduje umieszczenie tego w dziennikach błędów:
[Tue Oct 26 18:12:52 2010] [error] [client 71.61.190.56] script '/var/www/test.peopleareducks.com/rewrite/hi.txt.php' not found or unable to stat
Ale jest inna opcja, ustaw dyrektywy DefaultType
i w DirectoryIndex
ten sposób:
DefaultType application/x-httpd-php
DirectoryIndex index.php index.html
Aktualizacja 2013-11-14 - Poprawiono powyższy fragment, aby zawierał obserwację Nicorelliusa
Teraz prośby o plik hi.txt (i wszystko inne) są pomyślne, żądania do example.com/test zwrócą przetworzoną wersję test.php, a pliki index.php będą działać ponownie.
Muszę podać kredyt za to rozwiązanie, ponieważ znalazłem go na blogu Michaela J. Radwinsa , wyszukując w Google hasło php no extension apache .
Usuń końcowe ukośniki
Niektóre wyszukiwania apache remove trailing slashes
doprowadziły mnie do niektórych stron optymalizacji witryn pod kątem wyszukiwarek. Najwyraźniej niektóre systemy zarządzania treścią (w tym przypadku Drupal) udostępnią treść z końcowym ukośnikiem w adresach URls i bez niego, co w świecie SEO spowoduje, że Twoja witryna będzie ponosić karę za powielenie treści. Źródło
Rozwiązanie wydaje się dość trywialne, używając mod_rewrite
przepisywania pod warunkiem, że żądany zasób kończy się na a /
i przepisywania adresu URL przez odesłanie 301 Permanent Redirect
nagłówka HTTP.
Oto jego przykład, który zakłada, że Twoja domena to blamcast.net i pozwala na opcjonalne poprzedzenie żądania przedrostkiem www.
.
#get rid of trailing slashes
RewriteCond %{HTTP_HOST} ^(www.)?blamcast\.net$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
Teraz dokądś zmierzamy. Połączmy to wszystko razem i zobaczmy, jak to wygląda.
Obowiązkowe www.
, nie .php
i bez końcowych ukośników
Zakłada się, że domena to foobar.com i działa na standardowym porcie 80.
# Process all files as PHP by default
DefaultType application/x-httpd-php
# Fix sub-directory requests by allowing 'index' as a DirectoryIndex value
DirectoryIndex index index.html
# Force the domain to load with the www subdomain prefix
# If the request doesn't start with www...
RewriteCond %{HTTP_HOST} !^www\.foobar\.com [NC]
# And the site name isn't empty
RewriteCond %{HTTP_HOST} !^$
# Finally rewrite the request: end of rules, don't escape the output, and force a 301 redirect
RewriteRule ^/?(.*) http://www.foobar.com/$1 [L,R,NE]
#get rid of trailing slashes
RewriteCond %{HTTP_HOST} ^(www.)?foobar\.com$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
Flaga „R” jest opisana w RewriteRule
sekcji dyrektywy. Skrawek:
redirect|R [=code]
(wymuszenie przekierowania) Podstawienie przedrostka z
http://thishost[:thisport]/
(co sprawia, że nowy adres URL jest identyfikatorem URI), aby wymusić przekierowanie zewnętrzne. Jeśli nie zostanie podany żaden kod, zostanie zwrócona odpowiedź HTTP o wartości 302 ( PRZENIESIONA TYMCZASOWO ).
Uwaga końcowa
Nie udało mi się doprowadzić do pomyślnego usunięcia ukośnika. Przekierowanie dało mi nieskończone pętle przekierowań. Po bliższym przeczytaniu oryginalnego rozwiązania mam wrażenie, że powyższy przykład działa u nich z powodu konfiguracji ich instalacji Drupala. Wspomina konkretnie:
W normalnej witrynie Drupal, z włączonymi czystymi adresami URL, te dwa adresy są zasadniczo zamienne
W odniesieniu do adresów URL kończących się ukośnikiem i bez. Ponadto,
Drupal używa pliku o nazwie, .htaccess
aby poinformować serwer WWW, jak ma obsługiwać adresy URL. Jest to ten sam plik, który umożliwia czystą magię adresów URL w Drupalu. Dodając proste polecenie przekierowania na początku
.htaccess
pliku, możesz zmusić serwer do automatycznego usunięcia wszelkich końcowych ukośników.