Což si tak trochu zapřepisovat?

Michal Krause 4. 12. 2000

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.

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.

Našli jste v článku chybu?
Vitalia.cz: Očkování je nutné, říká homeopatka

Očkování je nutné, říká homeopatka

Měšec.cz: Do ostravské MHD bez jízdenky. Stačí karta

Do ostravské MHD bez jízdenky. Stačí karta

Vitalia.cz: Galerie: Strouhanka ze starých rohlíků? Kdepak

Galerie: Strouhanka ze starých rohlíků? Kdepak

Měšec.cz: Investiční pasti. Děláte to, co ostatní, ale proděláváte

Investiční pasti. Děláte to, co ostatní, ale proděláváte

Vitalia.cz: „Sjíždět“ porno není bez rizika

„Sjíždět“ porno není bez rizika

120na80.cz: Bylinka pro dobrý sex. Jaká to je?

Bylinka pro dobrý sex. Jaká to je?

Podnikatel.cz: Pozor na vykuky, imitují služby České pošty

Pozor na vykuky, imitují služby České pošty

DigiZone.cz: Hodlá Markíza skončit v DVB-T?

Hodlá Markíza skončit v DVB-T?

DigiZone.cz: Jetelín končí. Prima ho vyřadila

Jetelín končí. Prima ho vyřadila

Měšec.cz: Co když na dovolené přijdete o kartu?

Co když na dovolené přijdete o kartu?

Měšec.cz: Ceny PHM v Evropě. Finty na úspory

Ceny PHM v Evropě. Finty na úspory

Podnikatel.cz: Česká pošta vycouvala ze služby ČP Cloud

Česká pošta vycouvala ze služby ČP Cloud

Měšec.cz: Test: Výběry z bankomatů v cizině a kurzy

Test: Výběry z bankomatů v cizině a kurzy

Vitalia.cz: Musí moudrák opravdu ven?

Musí moudrák opravdu ven?

120na80.cz: Kam umístit silikony?

Kam umístit silikony?

Lupa.cz: Hackujete? Můžete mít problém sehnat práci

Hackujete? Můžete mít problém sehnat práci

Měšec.cz: Platíme NFC mobilem. Konečně to funguje!

Platíme NFC mobilem. Konečně to funguje!

Lupa.cz: Kdo vykrádá LinkedIn? Zjistit to má soud

Kdo vykrádá LinkedIn? Zjistit to má soud

Měšec.cz: Se stavebkem k soudu už (většinou) nemusíte

Se stavebkem k soudu už (většinou) nemusíte

Měšec.cz: Co s reklamací, když e-shop krachuje?

Co s reklamací, když e-shop krachuje?