Což si tak trochu zapřepisovat?

4. 12. 2000
Doba čtení: 4 minuty

Sdílet

Již delší čas je součástí distribuce Apache modul mod_rewrite. Má hodně příznivců (kteří obdivují jeho sílu) i odpůrců (kteří naopak poukazují na jeho složitost a "molochovatost"). Dnes se nechci ale věnovat tomu, zda mají pravdu ti první nebo ti druzí. Rád bych zde, na Rootovi, demonstroval postupně několik případů použití "přepisování" z praxe.

Nejdříve ale krátce přiblížím, co vlastně modul mod_rewrite je a k čemu slouží. Sami autoři jej přezdívají „švýcarským armádním nožem pro manipulaci s URL“ (nemusím snad vysvětlovat, že anglický termín „Swiss army knife of something“ se běžně používá pro označení univerzálních nástrojů a pochází skutečně od oblíbených kapesních nožů s mnoha funkcemi).

Nyní víme, že úkolem tohoto modulu je manipulace s URL (přepisování), neboli adresou konkrétního dokumentu. V praxi to znamená, že můžete změnit požadované URL na úplně jiné, a to jak formou přesměrování na externí zdroj, tak v podobě vnitřního (pro uživatele neviditelného) vyvolání jiného dokumentu. Na první pohled se může zdát, že to je velmi podobné běžnému přesměrování, jaké dělá v Apachi modul mod_alias. Je zde ale jeden podstatný rozdíl – přesměrování (nebo lépe řečeno přepsání) v mod_rewrite lze řídit neomezeným počtem podmínek, což umožňuje řešit relativně složité situace. Konec konců, naše příklady předvedou myslím možnosti přepisování poměrně působivě. Tak pojďme na to.

Příklad první: vše v jednom dokumentu

Možná jste se již někdy setkali s tím, že o celý web se stará jediný dokument, obvykle napsaný v nějakém skriptovacím jazyce. Je to poměrně praktické, neboť se velmi snadno mění a udržuje design a při vhodném rozdělení programu do více souborů (vkládaných do hlavního dokument) lze takový projekt udržet celkem přehledný i pro programátora. Velmi často používaný způsob, jak potom odlišit, co vlastně návštěvník chce vidět, je předávání nějakého parametru. A zde nastávají některé drobné problémy, z nichž nejpodstatnější je ten, že s takto organizovanými stránkami si neporadí některé vyhledávače. Například v PHP řešení tohoto problému existuje: parametry lze předat místo za otazníkem za lomítkem, jenom potom nejsou k dispozici v podobě zparsovaných proměnných, ale pouze jako celek v proměnné $PATH_INFO. To je pro naše účely poměrně ideální, neboť pro jednotlivé sekce serveru lze tvořit virtuální adresáře.

Výše popsané použití PHP funguje jaksi samovolně jenom tehdy, je-li v URL uveden přímo dokument, tedy například pro /testy/index.php3/vir­tualni_adresar – pak bude v proměnné $PATH_INFO řetězec „/virtualni_a­dresar“. Pokud bychom chtěli dosáhnout téhož cíle, ovšem přímým voláním adresáře /testy/, neuspějeme, i když bude index.php3 uveden jako regulérní výchozí soubor adresáře. Zde už je třeba na to jít jinak – je nutné vytvořit soubor (nikoliv adresář!) nazvaný testy a sdělit Apachi, že ať se mu to líbí nebo ne, soubor testy je PHP skript. K tomu slouží konfigurační direktiva ForceType (viz článek na PHP Builderu.

Po tomto značně obšírném úvodu se konečně dostáváme k mod_rewrite. Z výše popsaného totiž plyne jedna věc: celý mechanismus nelze použít, chceme-li, aby virtuální adresáře vznikly přímo pod kořenovým adresářem webu. Přidržíme-li se původního příkladu, není možné, aby v adrese /testy/ byl virtuálním už adresář testy. Respektive není to možné běžnými prostředky. S modulem mod_rewrite to ale zase až tak těžké není. O vše potřebné se postarají tyto dvě direktivy:

RewriteEngine On
RewriteRule ^/([^?]*)?(.*)$ %{DOCUMENT_ROOT}/index.php3/$1 [L,E=QUERY_STRING:$2]

První z nich pouze zapíná mod_rewrite a v případě, že je zapnut globálně, není nutné ji už ani uvádět. Veškerou práci tedy udělá řádek druhý, který si teď rozeberem.

  • Prvním parametrem direktivy RewriteRule je regulární výraz, který se aplikuje na aktuální URL. Jak uvidíme dále, budeme se chtít na jeho jednotlivé části zpětně odkazovat, proto ty závorky.
  • Druhým parametrem je cílové URL. Jak je vidět, lze v pravidlech používat různé proměnné. V některých případech je možné uvádět cestu i relativně, ale protože s tím mohou nastat různé komplikace, myslím, že je vhodnější držet se absolutní cesty a kvůli případnému přesunu virtuálu do jiného adresáře používat právě proměnnou DOCUMENT_ROOT.
    V URL je uveden i soubor index.php3, čímž obcházíme výše uvedené omezení (připomínám opět, že jde o vnitřní přesměrování, o kterém nemá uživatel ani potuchy). No, a původní celá cesta je připojena za lomítko pomocí zpětného odkazu $1 (na první závorku regulárního výrazu)
  • Třetím parametrem jsou tzv. příznaky (flags). Těmi můžeme různým způsobem ovlivnit chování výrazu. V našem případě jsou zde příznaky dva: L, což říká, že jde o poslední pravidlo v pořadí a že Apache už dále nemá aplikovat další podmínky a pravidla (která, jak vidno, lze i řetězit), a E, které slouží k nastavení proměnných prostředí. Příznak E nám umožňuje převzít původní parametry dotazu za otazníkem (jak je určeno regulárním výrazem) a znovu je předat PHP skriptu (pomocí nastavení proměnné QUERY_STRING na hodnotu získanou díky druhé zpětné refernci).

Jak vidíte, není to zase až tak složité, jak by se na první pohled mohlo zdát. Nyní se již můžete pustit do vlastních pokusů, ale nezapomeňte pokud možno na to, že cílem by mělo být vždy použití co možná nejefektivnějších nástrojů a funkcí a že třeba pro obyčejné přesměrování uživatele na jiný server je mod_rewrite doslova kanónem na vrabce.

ict ve školství 24

A závěrem bych si dovolil ještě odcitovat dva pány, kteří se na téma mod_rewrite vyjádřili velmi trefně takto:

Největším kladem mod_rewrite je to, že nabízí stejnou konfigurovatelnost a flexibilitu jako Sendmail. Naopak jeho největším záporem je fakt, že nabízí stejnou konfigurovatelnost a flexibilitu jako Sendmail.
Brian Behlendorf, Apache Group

Navzdory spoustě příkladů a dokumetnace, mod_rewrite je voodoo. Proklatě skvělé voodoo, ale přesto voodoo.
Brian Moore, bem@news.cmc.net

Případné zájemce o samostudium odkazuji na dokumentaci k modulu a také na „bibli přepisování“, dokument Apache URL rewriting guide.