Mod_rewrite je populární modul webového serveru Apache, který dovoluje snadno a efektivně manipulovat s URL, tedy s adresou dokumentů, které dostává uživatel do svého internetového prohlížeče. Hodí se nejen k zajištění přátelských adres třeba pro SEO, ale také pro řešení chyb, pro multihosting a další účely. Jak s ním pracovat?
Mod_rewrite dovoluje manipulovat s URL za použití neomezeného počtu pravidel. Každé z těchto pravidel navíc může být doplněno neomezeným počtem podmínek, takže můžete provádět manipulace s využitím serverových proměnných, proměnných prostředí, HTTP hlaviček apod. Pravidla pro mod_rewrite mohou být realizována prostřednictvím souborů httpd.conf nebo .htaccess – což už dnes podporuje zřejmě většina i velmi levných web hostingů. Rovněž samotný mod_rewrite je dnes běžnou součástí nabídek linuxových web hostingů.
Dost ale úvodního povídání, pojďme na konkrétní příklady.
Chcete li mod_rewrite používat, je třeba ho v .htaccess nejprve zapnout. To uděláte snadno příkazem RewriteEngine on.
Základní direktivou při využití mod_rewrite je příkaz RewriteRule. Jeho syntaxe je snadná: RewriteRule požadovaná-adresa skutečná-adresa [volitelné přepínače]. Jak to funguje? Když návštěvník stránek požaduje dokument s adresou požadovaná-adresa, mod_rewrite mu poskytne dokument s adresou skutečná-adresa. Může to přitom udělat tak, že návštěvníkovi novou adresu sdělí (přesměruje ho a v prohlížeči se ukáže nová URL), nebo ji před ním zatají (v prohlížeči se ukazuje stále ta URL, kterou zadal návštěvník). K tomu slouží přepínač R.
Jak to bude vypadat v praxi? Třeba takto:
RewriteRule ^slozka/stranka.php nova-stranka.php
Když pak uživatel zadá do prohlížeče adresu http://neco.cz/slozka/stranka.php, zobrazí se mu obsah stránky http://neco.cz/nova-stranka.php. V URL ale zůstane původní adresa. Znak ^ přitom říká, že znaky, které za ním následují, jsou na začátku přesměrovávané adresy. Mohli bychom zde použít i znak $ takto:
RewriteRule ^slozka/stranka.php$ nova-stranka.php
Znak $ říká, že předcházející znaky jsou na konci přesměrovávané adresy.
Pokud zadáte pravidlo:
RewriteRule ^slozka/stranka.php nova-stranka.php [R]
stane se totéž, ale adresa v adresním řádku prohlížeče se změní na http://neco.cz/nova-stranka.php. Dojde tedy k přesměrování, nikoli jen k dodání obsahu z "náhradní" adresy.
Za přepínač R přitom můžete doplnit, o jaké přesměrování se jedná. Zapíšete-li tedy R=301, jde o permanentní přesměrování, pro 302 o dočasné.
Na místě je zmínit ještě direktivu RewriteBase, která určuje URL prefix pro .htaccess příkazy, kterými nahrazujete relativní cestu. Nahrazujete-li od dané složky výš, použijete příkaz v podobě:
RewriteBase /
Nyní tedy dejme vše výše zmíněné dohromady a vytvořme v textovém editoru náš první soubor .htaccess využívající mod_rewrite. Bude vypadat takto:
RewriteEngine On
RewriteBase /
RewriteRule ^slozka/stranka.php nova-stranka.php [R=301]
Na začátku jsme tedy zapnuli mod_rewrite, poté nastavili prefix a následně určili, že se adresa slozka/stranka.php přesměruje na nova-stranka.php a půjde o permanentní přesměrování.
Lze ovšem použít i sofistikovanější způsoby přesměrování/náhrady obsahu, a to díky regulárním výrazům a proměnným. Pro další příklady už vždy budeme předpokládat, že jste v úvodu souboru .htaccess použili příkazy RewriteEngine On a RewriteBase / a nebudeme je tedy opakovat.
A pojďme tedy rovnou k proměnným a regulárním výrazům. Třeba v tomto příkladu:
RewriteRule ^sys_([0-9]+)$ sys/cache.php?data=$1 [L,NC,QSA]
Co se tu děje? Znak ^, jak víme, říká, že zde je začátek přesměrovávané adresy. Jde tedy o adresu sys_ a něco za ní. Kulaté závorky přikazují uložit další znaky do proměnné, přičemž jednotlivé proměnné jsou číslované od jedné a značené znakem $ (pozor, zde je tento znak ale použit nikoli v levé části příkazu, ale v pravé – tedy v té, která určuje, kam se přesměrovává), zde tedy $1. Hranaté závorky nahrazují jeden znak, v tomto případě znak z množiny 0-9. Plus za hranatou závorkou říká, že nepůjde o jeden znak, ale o jeden nebo více (hvězdička by říkala, že půjde o 0 nebo více). A co se tedy přesměrovává? Třeba adresa http://neco.cz/sys_01. Nebo http://neco.cz/sys_993. Nebo http://neco.cz/sys_68. Prostě adresa začínající (za názvem domény) znaky sys_ a pokračující alespoň jedním znakem z množiny 0-9. Přičemž tyto znaky se uloží do proměnné $1. U http://neco.cz/sys_01 se uloží 01, u http://neco.cz/sys_993 se uloží 993, u http://neco.cz/sys_68 se uloží 68.
A jaký dokument uživatel získá? Pravidlo říká, že sys/cache.php?data=$1, tedy ve výše uvedených případech http://neco.cz/sys/cache.php?data=01, http://neco.cz/sys/cache.php?data=993 nebo http://neco.cz/sys/cache.php?data=68. Protože v přepínačích není R, v adresním řádku prohlížeče nadále zůstane původní adresa. A když jsme u těch přepínačů: L říká, že po tomto nahrazení už se mají další příkazy ignorovat. NC říká, že nezáleží na velikosti písmen. A QSA říká, že je třeba připojit i proměnné z URL, takže se neztratí např. a=1 z příkazové řádky – z adresy http://neco.cz/sys_01?a=1, ale pěkně se předá serveru ke zpracování i na nové adrese.
Znaky [0-9]+ samozřejmě nepředstavují jediný regulární výraz – v jejich tvorbě máte velkou volnost. Spíše než jejich detailnějšímu vysvětlování, které by zabralo samostatný článek, ne-li jejich sérii, uveďme ještě několik dalších příkladů regulárních výrazů. Takže:
[0-9a-z] = libovolný ze znaků 0-9 nebo a-z, tedy např. q, 9, a
[0-9a-z]* = libovolný počet znaků 0-9 nebo a-z, tedy např. q9as, 9ujk, am8klp, ale i prázdný řetězec
[0-9a-z]+ = totéž, jako o řádek výše, ale musí jít o nejméně jeden znak
[0-9a-zA-Z-_]+ = totéž, jako o řádek výše, ale povoleny jsou i znaky pomlčka (-) a podtržítko (_)
ahoj = ahoj
ah[ou]j = ahoj nebo ahuj (ano, [] je stále jeden znak z uvnitř uvedených)
[^0-9] = jakýkoli znak kromě znaků 0-9 (v hranaté závorce je znak ^ znakem negace)
[^0-9a-z] = jakýkoli znak kromě znaků 0-9 a a-z
[\\x] = \ nebo x (\ je speciální znak, musí mu tedy předcházet znak \)
.* = jakékoli znaky (tečka, tedy ., znamená libovolný znak (zpravidla kromě přechodu na nový řádek), * pak znamená v jakémkoli počtu)
.+ = alespoň jeden znak, jakýkoli
^(www\.)?domena\.cz$ = domena.cz nebo www.domena.cz (všimněte si zpětných lomítek před speciálním znakem tečka a otazníku, který říká, že ono www. tam být může a nemusí).
Dalším důležitým příkazem pro využití manipulací s URL, které nabízí mod_rewrite, je RewriteCond. RewriteCond definuje podmínku pro následující pravidlo RewriteRule, přičemž jednomu RewriteRule může předcházet více takových podmínek. RewriteRule je pak používáno, když jsou splněny předcházející podmínky – a když URL samozřejmě odpovídá vzoru v RewriteRule.
V RewriteCond lze užít řadu proměnných, mimo jiné HTTP_HOST (adresa/URL hostitele), HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE, SERVER_NAME, SERVER_PROTOCOL nebo třeba TIME_MON.
Příklady podmínek pak mohou vypadat třeba takto:
RewriteCond %{HTTP_HOST} ^(www\.)?domena\.cz$
Znamená: Pokud je hostitelem domena.cz nebo www.domena.cz, pak... Levá strana je v tomto případě proměnná hostitel, vpravo je regulární výraz, kterému musí odpovídat, aby byla podmínka splněna.
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?domena\.cz [NC]
Znamená: Pokud se na dokument odkazuje z jiné domény, než z domena.cz nebo www.domena.cz... (Vykřičník zde znamená negaci.) Tuto podmínku lze s výhodou použít jako součást řešení, které zabrání hotlinkování obrázků. Přepínač NC znamená totéž, co u RewriteRule, tedy platnost bez ohledu na velikost písmen ve výrazu.
Některé web hostingy využívají mod_rewrite a .htaccess v uživatelově složce také k realizaci multihostingu. V ČR je to například hosting WeDos. Toto řešení sice není příliš elegantní – a vyžaduje na straně uživatele občas trochu experimentování, ale svou funkci splní.
Hostingový účet samozřejmě musí být nastaven tak, aby byl schopen přijmout požadavek na zobrazení dokumentů z dané domény. Samotné určení, odkud jsou pak dokumenty poslány, zařídí mod_rewrite například s takovými prvky v .htaccess:
RewriteRule ^domenaX(.*)$ domenaX$1 [L,NC,QSA]
RewriteCond %{HTTP_HOST} ^(www\.)?domenax\.cz$
RewriteRule ^(.*)$ domenaX/$1 [L,NC,QSA]
Jak to bude fungovat? Předpokládejme, že daný soubor je v root složce hostingového účtu, odkud jsou řešeny požadavky na dodání dokumentů z webu. Obsah domény domenax.cz je pak dodáván z podsložky domenaX. První RewriteRule zajistí, že když už je požadován dokument (html, php, obrázky apod.) z podsložky domenaX, nedojde už k žádnému dalšímu nahrazování ani přesměrování. Pokud není požadován dokument z této složky, jde se dál – a zkoumá se, zda se požadavek na dokument vztahuje k doméně domenax.cz nebo www.domenax.cz. Pokud je tomu tak, díky následujícímu RewriteRule dojde k zajištění toho, že se dokument opravdu dodá ze složky domenaX.
Pokud je požadavek vznesen na jinou doménu, musí to řešit další řádky tohoto souboru .htaccess, nebo samozřejmě může být použito přirozeného směrování - tj. bez ovlivňování výsledku souborem .htaccess.
Dodejme, že pokud by první RewriteRule chybělo, skončil by celý proces v nekonečné smyčce. Požadavky na domenax.cz by se „odesílaly“ na podsložku domenaX, pro tyto požadavky by se znovu zkoumal .htaccess, opět by byla splněna podmínka domény, znovu by došlo k odeslání do této složky atd.
Zbývá tedy jen přidat varování: Pozor při tvorbě a úpravách souboru .htaccess na chyby. V jejich důsledku můžete snadno dosáhnout znefunkčnění svého webu. Lze tedy doporučit při tvorbě testovat a kontrolovat - a pro jistotu i ihned po nahrání nového souboru otestovat funkčnost stránek. Pokud vše nefunguje tak, jak má, vše rychle napravíte nahráním původního souboru, případně prostě smazáním svého souboru .htaccess, pokud předtím na serveru žádný nebyl. A upravujete-li pravidla v souboru http.conf, je po jejich změně třeba restartovat server.
Možnosti mod_rewrite jsou ještě výrazně širší, pro přehled dalších proměnných a direktiv lze doporučit třeba přímo stránku mod_rewrite Apache. Pro pronikání do tajů regulárních výrazů pak třeba stránky www.regular-expressions.info. Věříme však, že pro základní seznámení a některé jednodušší úkoly si vystačíte i s tímto naším úvodem do problematiky.
Diskutovat k tomuto tématu můžete nejen zde pod článkem, ale také na diskusním serveru pro profesionály Bizio.cz - mod_rewrite.