• Strona główna
  • Curriculum Vitae
  • O mnie
  • Mapa strony
  • Kontakt
Niebieski Pomarańczowy Zielony Różowy Fioletowy

Kiedy nie używać mod_rewrite?

Opublikowane 14 lutego 2010. Autor: Kamil Brenk. Wizyt: 302.

Kategorie: Apache
Tematyka: Apache, mod_alias, mod_proxy, mod_rewrite, mod_vhost_alias, serwery wirtualne, Wyrażenia regularne

lut 14

Moduł mod_rewrite to nie tylko “przyjazne” adresy URL. mod_rewrite jest modułem Apache, którego funkcjonalność jest przeogromna – o czym często nawet administratorzy serwerów nie wiedzą. A jeszcze częściej wiedzą i wykorzystują tam, gdzie nie powinni. Trzeba jednak pamiętać, że mod_rewrite to nie lekarstwo na każdy problem!

W poście tym zamierzam przedstawić kilka alternatywnych rozwiązań, które będą wygodniejsze w użyciu, bardziej optymalne oraz skalowalne.

Przepisywanie adresów URL

Pewnie trochę Cię to zdziwi, ale dlaczego nie zaleca się przepisywania linków za pośrednictwem tego modułu? Sposób ten jest prosty i pozwala w bardzo krótkim czasie stworzyć “przyjazne” linki dla całego serwisu.

Jednak uzależnianie się od jednego serwera (w tym przypadku Apache) jest błędem. Twój serwis powinien być skalowalny, a to znaczy, że powinno być możliwe bezproblemowe przeniesienie serwisu na inny serwer HTTP (np. IIS, nginx czy Lighttpd). Wystarczy, że nowy serwer nie będzie obsługiwał mod_rewrite i zabawa przepisywania linków zaczyna się od nowa :)

Wykorzystywanym przeze mnie rozwiązaniem jest stosowanie ustawień podobnych do tych oferowanych przez WordPress, tzn.:

1
2
3
4
5
6
7
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

W ten sposób każde odwołanie trafia do pliku index.php, w którym następnie specjalna klasa tłumaczy i przyporządkowuje “przyjazne” linki do rzeczywistych im adresów. Efekt taki sam jak w przypadku mod_rewrite, ale skalowalność dużo większa.

Zwykłe przekierowania

W wielu miejscach w sieci można poczytać o przekierowaniach za pośrednictwem .htaccess. Prezentowane przykłady opierają się na mod_rewrite i dyrektywie RewriteRule z flagą R.

Dlaczego ten sposób jest niezalecany? Gdyż od przekierowywania są specjalne reguły rozpoznawane przez serwer Apache, typu Redirect, RedirectMatch czy ProxyPass.

  1. Redirect
    Pozwala na wykonywanie prostych przekierowań – metoda ta jest najszybsza i pozwala na wykonywanie przekierowań typu jeden-do-jednego. Przykładowe zastosowania:
    1
    Redirect 301 / http://nowy.adres.pl/
    1
    Redirect pliki/ http://nowy.adres.pl/pliki/
  2. RedirectMatch
    Reguła podobna do powyższej, lecz powala na stosowanie bardziej skomplikowanych przekierowań, budowanych przy pomocy wyrażeń regularnych. Przykładowe zastosowanie:
    1
    RedirectMatch 301 (.*)\.jpg http://nowy.adres.pl/zdjecia/$1
  3. ProxyPass
    Reguła ta pozwala na wykonywanie przekierowań z wykorzystaniem serwera proxy. Przekierowania takie wykorzystują moduł mod_proxy i mają zastosowanie między innymi przy rozdzielaniu obciążenia na kilka serwerów. Przykładowe zastosowanie:
    1
    2
    3
    4
    5
    6
    7
    8
    <IfModule mod_proxy.c>
    # bezpieczeństwo - wyłaczenie pośrednictwa zwrotnego
    ProxyRequests Off

    # właściwe przekierowanie niewidoczne dla użytkownika
    ProxyPass / http://nowy.adres.pl/
    ProxyPassReverse / http://nowy.adres.pl/
    </IfModule>

    Chcąc wykorzystać mod_proxy do bardziej skomplikowanych operacji (np. pobranie obrazków z innego serwera niewidoczne dla klienta) można połączyć mod_proxy z mod_rewrite. Wygląda to następująco:

    1
    2
    3
    RewriteEngine On
    RewriteRule (.*\.jpg) http://zdjecia.strona.pl/$1 [P]
    ProxyPassReverse / http://zdjecia.strona.pl/
Serwery wirtualne

Moduł mod_rewrite można zastosować także do dynamicznego tworzenia serwerów wirtualnych. Jednak przed takim wykorzystaniem modułu warto rozważyć alternatywne rozwiązania. Istnieją bowiem dedykowane moduły utworzone specjalnie na cele serwerów wirtualnych. Mowa tutaj o mod_vhost_alias. Oczywiście warto wspomnieć o standardowych serwerach wirtualnych, domyślnie obsługiwanych przez serwer Apache.

Na korzyść mod_vhost_alias przemawia między innymi fakt, iż moduł ten pozwala odwzorowywać nazwy domenowe na nazwy katalogów. Umożliwia to dodawanie nowych nazw domenowych bez zmian w pliku konfiguracyjnym – czego nikt nie lubi.

Kontrola dostępu na podstawie adresu

Moduł mod_rewrite dzięki swojej warunkowej dyrektywie RewriteCond pozwala efektywnie blokować dostęp wybranym adresom IP, między określonymi godzinami czy dla różnych agentów przeglądarek. Jednak rzadko kiedy faktycznie wykorzystywane są powyższe sposoby blokowania treści, a najczęściej zabezpieczana jest jedynie wybrana część serwisu.

W tym celu nie należy korzystać z tego modułu. Wystarczającym rozwiązaniem jest zastosowanie serwerowych dyrektyw allow i deny dla danych folderów i miejsc na serwerze.

1
2
3
4
5
 <Directory /www/admin/>
     Order allow,deny
     Allow from 121.0.
     Deny from all
 </Directory>

Lub w bardziej skomplikowanym przypadku (z wykorzystaniem wyrażeń regularnych):

1
2
3
4
 <DirectoryMatch "^/www/.*/[0-9]{3}">
     Order allow,deny
     Allow from all
 </Directory>
Podsumowanie

Warto pamiętać, że moduł mod_rewrite został napisany w 1996 roku i nie zawsze może być najlepszym rozwiązaniem. Wiele innych rozwiązań pozwala na efektywniejsze zarządzanie serwerem i rzadko kiedy tak naprawdę potrzebujesz tego modułu.

Moja rada jest więc następująca: zamiast upatrywać się wszelkich miejsc, gdzie tylko możesz zastosować mod_rewrite, zacznij korzystać z tego modułu jedynie w sytuacjach bez wyjścia – jako ostatnią deskę ratunku. Powodów jest kilka, między innymi wykorzystywanie niewydajnych wyrażeń regularnych czy niepotrzebne aktywowanie kolejnego modułu, co również wydłuża działanie serwera Apache.

Komentarze (3)

  1. Michal Wachowski 14 lutego 2010

    Używam podobnego rozwiązania z pierwszego przykładu – różnica jest znikoma.

    1
    2
    3
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ ?furl=$1&%{QUERY_STRING}

    Jednym if’em załatwiam sprawdzane czy jest friendly czy nie.

    Nie chcę siać fermentu – ale część rzeczy nie jest realizowana przez ModRewrite – po prostu możliwości .htaccess są przeogromne.

    I jeszcze taka mała uwaga – RewriteBase nie jest wymagany, czasem przydatny, czasem szkodzi.

  2. Kamil Brenk 15 lutego 2010

    Właśnie w tej notce chciałem opisać miejsca, w których nadużywa się modułu mod_rewrite. Jest wiele innych modułów i dyrektyw Apache, które działają optymalniej (choćby przez niewykorzystywanie niewydajnych wyrażeń regularnych). Z tego co zauważyłem, zwłaszcza wśród pozycjonerów i przekierowań – ich problemy możnaby w dużo prostszy sposób rozwiązać (Redirect, RedirectMatch).

     

    1
    RewriteRule ^(.*)$ ?furl=$1&%{QUERY_STRING}

    Co do Twojej regułki mam pewną uwagę: wzorzec o wartości ^(.*)$ wymusza na mechanizmie wyrażenia regularnego przeanalizowanie całego ciągu tekstowego i porównanie każdego znaku z symbolem wieloznaczności . w celu sprawdzenia, czy znak pasuje do wzorca. Oczywiście każdy znak pasuje do wzorca . – jednak ciąg o n znakach będzie powodował wykonanie n operacji porównania.

    W przypadku wzorca z WordPress sprawa wygląda następująco:

    1
    RewriteRule . /index.php [L]

    Czyli od razu cała treść adresu URL jest przekazana do pliku index.php :)

  3. Michal Wachowski 15 lutego 2010

    Różnice są w pobieraniu wywołanego adresu

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // index.php znajduje się w http://domena.com/katalog/
    // $_GET['furl'] - moja wersja

    // dla adresu http://domena.com/katalog/pl/artykuly/tytul.html
    $HTTP_SERVER_VARS['PATH_INFO'] # nic
    $_SERVER['REQUEST_URI'] # /katalog/pl/artykuly/tytul.html
    $_SERVER['PATH_INFO'] # nic
    $_GET['furl'] # /pl/artykuly/tytul.html

    // dla adresu http://domena.com/katalog/index.php/pl/artykuly/tytul.html
    $HTTP_SERVER_VARS['PATH_INFO'] # /pl/artykuly/tytul.html
    $_SERVER['REQUEST_URI'] # /katalog/index.php/pl/artykuly/tytul.html
    $_SERVER['PATH_INFO'] # /pl/artykuly/tytul.html
    $_GET['furl'] # nic

    Możliwe, że coś pominąłem…

    Enyłej, po wpisaniu ‘php frienldy url’ w googlach, wyniki są … masakrujące.
    Tutoriale jak stworzyć potworki pokroju index.php/pl/artykul/tytul.html, albo przygotowywanie wyrażenia regularnego dla każdego wariantu adresu…
    Heh! Że też im się chce…



Dodaj komentarz

XHTML: Możesz użyć następujących tagów
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang="" escaped=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Kamil Brenk Blog

PHP, JavaScript, SQL, HTML

  • Informacje o blogu

    Kamil Brenk

    Blog o tworzeniu aplikacji na potrzeby sieci Web.

    Praktyczne przykłady, porady i sztuczki. PHP, SQL, AJAX, JavaScript, HTML i pochodne.

    Kanał RSS

    • Najnowsze
    • Komentarze
    • Popularne
    • Konwersja JS i CSS do PNG
    • Optymalizacja wyrażeń regularnych
    • Cross-Domain JavaScript
    • Kompendium programisty #1
    • Jak pobierać zewnętrzne zasoby?
    • 960 Grid System
    • Kamil Brenk: @eN: Nie sposób się nie zgodzić z tym co piszesz, masz...
    • Michal Wachowski: To jest na prawdę szalone :D
    • The one: Zarąbista gierka :D
    • eN.: Problem w tym że nie zwracają tego samego, a dokładniej1...
    • Michal Wachowski: DAS - deterministyczne automaty skończone, AS - to samo ale bez...
    • Kamil Brenk: DAS / AS? Pierwsze słyszę :-) Raczej nie będę już miał...
    • Michal Wachowski: Jak na studiach będziesz mieć AS i DAS to wiele się wyjaśni...
    • Gramatyka w PHP, część 1
    • Projekt aplikacji po stronie klienta
    • Optymalizacja wyrażeń regularnych
    • Yii PHP Framework vs Symphony
    • Minimalizacja zapytań HTTP
    • Jak pobierać zewnętrzne zasoby?
    • Usługi sieciowe w PHP: REST
  • Szukajka
    Wpisz co chcesz wyszukać na stronie…
  • Kategorie
    • Apache
    • Front-end Development
    • HTML5 & CSS3
    • Inne
    • JavaScript
    • PHP
    • Po godzinach
    • Protokół HTTP
    • SQL
    • Wyrażenia regularne
  • Moje serwisy
    • Testy zawodowe
    • Miłość, uczucia i seks
  • Czytane blogi
    • Wojciech Sznapka
    • Wojciech Soczyński
    • Dzienniki zyxowe
    • Przemysław "eRIZ" Pawliczuk
  • Archiwum
    • sierpień 2010
    • lipiec 2010
    • czerwiec 2010
    • maj 2010
    • kwiecień 2010
    • marzec 2010
    • luty 2010
    • styczeń 2010
  • Strona główna
  • Curriculum Vitae
  • O mnie
  • Mapa strony
  • Kontakt

Kamil Brenk © 2010. All rights reserved.

Designed by FTL Wordpress Themes brought to you by Smashing Magazine.

Do góry ∧