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.

120na80.cz: Vyzrajte na návaly a pocení v přechodu

Vyzrajte na návaly a pocení v přechodu

DigiZone.cz: Nová pravidla EK pro AV slu­žby

Nová pravidla EK pro AV slu­žby

Lupa.cz: Kam si doma dáte internet věcí? Na polici?

Kam si doma dáte internet věcí? Na polici?

Lupa.cz: Jak EET vidí ajťák aneb Drahá vražda UX

Jak EET vidí ajťák aneb Drahá vražda UX

120na80.cz: Zjistěte, zda je vaše klíště infikované

Zjistěte, zda je vaše klíště infikované

Podnikatel.cz: Šizený guláš na pultě. Jako Lidl to nedělejte

Šizený guláš na pultě. Jako Lidl to nedělejte

Root.cz: Zákon o hazardu je v rozporu s ústavou

Zákon o hazardu je v rozporu s ústavou

Lupa.cz: Přenos hokeje padal kvůli útoku, tvrdí O2

Přenos hokeje padal kvůli útoku, tvrdí O2

Vitalia.cz: Mražené ryby z Makra byly falšované

Mražené ryby z Makra byly falšované

DigiZone.cz: UPC umí televizi sedm dní nazpět

UPC umí televizi sedm dní nazpět

DigiZone.cz: Šlágr TV: pokuta 100 tisíc za on-line

Šlágr TV: pokuta 100 tisíc za on-line

Vitalia.cz: Ministerstvo: tyto příbory jsou nebezpečné

Ministerstvo: tyto příbory jsou nebezpečné

Vitalia.cz: SÚKL: vakcíny jsou bezpečné a s autismem nesouvisí

SÚKL: vakcíny jsou bezpečné a s autismem nesouvisí

DigiZone.cz: ČT neskončí s nízkým rozlišením podle plánu

ČT neskončí s nízkým rozlišením podle plánu

Lupa.cz: Válka e-shopů. Alza končí s Heurekou

Válka e-shopů. Alza končí s Heurekou

Podnikatel.cz: Proměny stavebnice Seva. Znáte ji?

Proměny stavebnice Seva. Znáte ji?

Vitalia.cz: Tetanus v USA – i po odřeninách

Tetanus v USA – i po odřeninách

Vitalia.cz: Před, nebo po snídani? Kdy je lepší čistit si zuby

Před, nebo po snídani? Kdy je lepší čistit si zuby

DigiZone.cz: DAB+ versus FM, ČRo a ČRa proti APSV

DAB+ versus FM, ČRo a ČRa proti APSV

Vitalia.cz: Dnešní patolog o mrtvolu téměř nezavadí

Dnešní patolog o mrtvolu téměř nezavadí