RSS: Vše - Programování



Apache a mod_rewrite

13. 11. 2007, 18:34:59,Programování,

Mod_rewrite patří určitě mezi ty nejvíce užitečné ale zároveň nejméně známé moduly webového serveru Apache. Postupem času jeho význam ještě vzrůstá a dnes už je téměř v každém internetovém projektu přítomen notoricky známý soubor .htaccess, obsahující nějaké ty rewrites pro hezká URL, aliasy atp. Přitom si ale tato problematika udržuje pověst "černé magie", které rozumí jen odborníci. Určitě k tomu přispívá i fakt, že mod_rewrite je postaven na regulárních výrazech, jejichž znalost není u začínajících a mírně pokročilých programátorů nijak velká.

Pokusím se s vámi projít nutné základy problematiky regulárních výrazů a pak nejběžnější použití direktiv RewriteRule a RewriteCondition, a to včetně příznaků. Doufám, že zjistíte, že se nejedná o žádné woodoo a že se vám mnoho zde uvedených příkladů a informací bude hodit.

Regulární výrazy

Zvládnout regulární výrazy není tak obtížné, jak se může na první pohled zdát. Celé kouzlo vlastně spočívá pouze ve správném pochopení několika málo speciálních symbolů a jejich správného použití:

  • . - tečka, značí libovolný znak. Například vzoru a.t vyhovují řetězce art, factory či pantaloons
  • * - hvězdička, značí libovolný počet opakování (nula nebo vícekrát). Vzoru at* vyhovují tedy řetězce a, at i kattttt.
  • + - plus, značí, že se znak či atom (viz. níže) může opakovat, nejméně však jednou
  • ? - otazník značí, že uvedený znak může i nemusí být přítomen. Například vzor colou?r pojme obě varianty anglického výrazu pro barvu (britské colour i americké color)
  • ^ - "vsuvka", která říká, že tímto vzorem musí řetězec začínat. Vzoru ^a tedy vyhovuje například řetězec abbb, ale už ne baaa
  • $ - dolar, značí, že tímto vzorem musí řetězec končit. Vzoru a$ tedy vyhovuje například Amerika, ale už ne rak.
  • () - závorky mají dvojí funkci. Jednak seskupují znaky do atomu, na který se pak aplikují výše uvedené speciální symboly jako na celek (Například vzoru (ab)+ vyhovuje ababab), jednak označují části výrazu pro pozdější použití. První množina znaků uzavřená v závorkách je později dostupný pod proměnnou $1 (nebo %1 podle kontextu použití), druhá pod proměnnou $2 atp.
  • [] - hranaté závorky, umožňují definovat množinu možných znaků. Například ^t[aeu]k$ vyhovuje řetězcům tak, tek i tuk. Použít můžeme i pomlčku, jakožto značku pro rozsah - namísto vzoru [01234567] můžeme ve zkratce psát [0-7].
  • ! - vykřičník, umožní nám negovat libovolný vzor. Pokud tedy před vzor napíšeme vykřičník, bude vyvohovat přesně opačné množině řetězců.
Pokud chcete tyto speciální znaky použít v jejich původním významu, měli byste před ně zapsat symbol \, který jejich speciální funkci potlačí.

RewriteRule

Direktiva RewriteRule je tím nejdůležitějším nástrojem pro přesměrování požadavků, vytváří totiž tzv. pravidla. Používá se ve tvaru

RewriteRule a b [flags]
kde a je regulární výraz, který popisuje požadavek, b je adresa, na kterou je původní požadavek transformován a flags jsou čárkami oddělené příznaky, které dokáží měnit původní význam příkazu. Kupříkladu kód v podobě
RewriteEngine On
RewriteRule \.gif$ b.html
říká, že budeme používat mod_rewrite (první řádek) a že všechny požadavky na soubory gif (požadavky končící na ".gif") na našem serveru, budou přesměrovány na soubor b.html.

Flags

Následuje seznam několika nejzajímavějších příznaků:

  • C (Chain)- Tento příznak říká, že je pravidlo navázáné na následující. Následující pravidlo je tedy použito pouze tehdy, když URI vyhovuje prvnímu pravidlu. V ostatních případech je druhé, navázané pravidlo přeskočeno.
  • H (Handler) - Tento příznak říká, že vyhovující požadavky budou obslouženy definovaným handlerem. Například pokud chceme, aby všechny soubory bez koncovky byly zpracovány interpretem PHP, můžete napsat
    RewriteRule !\.-[H=application/x-httpd-php]
    (všimněte si zápisu - nejprve vezmeme všechny URI, které obsahují tečku a pak to znegujeme, takže dostaneme všechny URI, které tečku neobsahují)
  • L (Last) - Jednoduše řekne serveru, že se jedná o poslední rewrite a žádná následující pravidla nemá zpracovávat
  • P (Proxy) - Velice důležitý příznak, umožňuje přesměrovat požadavky na jiný server. Například, pokud chcete mít na pozadí druhý server a všechny obrázky načítat z něj, můžete to zapsat takto:
    RewriteRule (.*)\.(jpg|gif|png) http://images.nekde.cz$1.$2 [P]
  • QSA (QueryStringAppend) - Příznak, ketrý zajistí to, že po přesměrování neztratíte předávané parametry. Kupříkladu při použití pravidla
    RewriteRule /pages/(.+) /page.php?page=$1 [QSA]
    se URI pages/123?a=b přemapuje na /page.php?page=123&a=b
  • R (Redirect) / Příznak, který vám umožní provést HTTP redirect na plně zadané URL.

Další zajímavé příznaky můžete najít v dokumentaci Apache.

RewriteCond

Direktivy RewriteCond slouží ke dvěma hlavním účelům. Jednak umožňují kombinovat mnoho jednotlivých dílčích podmínek pro pravidla a jednak umožňuje přístup i k proměnným, ke kterým RewriteRule přístup nemá. Těmito proměnnými mohou být v URL předávané parametry (část za otazníkem), hostname, aktuální den, čas atp. Dva jednoduché příklady pro ilustraci.

RewriteCond %{QUERY_STRING} prod=(.*)
RewriteRule ^/index.html /products/%1.html [PT]

Tento příklad dokáže požadavky typu http://server.cz/index.html?prod=kites přeložit na /products/kites.html. Všimněte si použití znaku % namísto $ při odkazování se na elementy získané v direktivě RewriteCond.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.php [PT]

Tímto způsobem lze ošetřit požadavky, které by jinak skončily hláškou "File Not Found". Operátor -f testuje existenci (a možnost ho číst) souboru, operátor -d existenci adresáře. Díky negaci použitých výrazů dostaneme množinu všech požadavků, které směřují na neexistující soubory.

Další užitečné informace naleznete v oficiální dokumentaci a v mod_rewrite wiki. Základem pro tento úvod byl moc hezký článek Riche Bowena "Introducing mod_rewrite" uveřejněný v časopise PHP Architect.

Autor: Pavel Šindelka

Komentáře


[1] (Orcslayer) - 14. 11. 2007, 16:08:26
Pěkné. :) Mod_rewrite už mi dlouho hnije v nepřečtených záložkách, tak se k tomu třeba rychleji dokopu. :)
[2] (kemo) - 17. 11. 2007, 10:44:23
Dobrý den, měl bych jeden dotaz, ohledně mod_rewrite. Konkrétně se jedna o to, že se nachází v adrese více než jeden parametr. Např: portfolio.php?id=grafika&orderby=datum&type=asc

Chtěl bych se zeptat, jak by vypadalo pravidlo pro tuto adresu, aby adresa v adresním řádku vypadala např takto:
domena.cz/portfolio/datum/asc

zatím mam toto pravidlo ale stále se mi nedaří jej rozšířit o další parametry

RewriteRule ^portfolio/([a-zA-Z0-9\\-]*)$ portfolio\.php?id=$1 [L,NC]
[3] (Pavel Šindelka) - 17. 11. 2007, 13:26:32
[2] Mělo by to fungovat na stejném principu jako s jedním parametrem. Zkusil jsem udělat rewrite pro dva parametry:
RewriteRule ^portfolio/([a-zA-Z0-9\\-]*)/([a-zA-Z0-9\\-]*)$ /portfolio.php?prvni=$1&druhy=$2 [L,NC]

Mně to běželo OK, když jsem to testoval, tak snad pomůžu :)
[4] (Pepíno) - 12. 03. 2008, 20:57:29
Pěknej článek, nejsrozumitelnější, co jsem na tohle téma našel :o). Myslím, že jsem to i pochopil, akorát mi to pořád tak nějak nedělá to, co chci :o).

Potřeboval bych zajistit, aby mi z webu nešly stáhnout fotky přímým zadáním cesty na ně např. http://www.neco.cz/Data/Fot..., takže přijatá adresa, co obsahuje Data nebo .jpg se má změnit na domovskou adresu.

Zkoušel jsem do .htaccess dát

RewriteEngine on

a vždy jeden z těchhle řádků a ani jedno z toho nezabralo.

RewriteRule \.jpg$ http://www.neco.cz/index.php
RewriteRule .*Data.* index.php
RewriteRule \.jpg$ http://www.neco.cz
RewriteRule .*Data.* http://www.neco.cz/index.php

Soubor .htaccess mám v kořeni se souborem index.php, nejsem si jistý, jestli je RewriteRule správně, ale takhle jsem to pochopil :o).

Takže, kdyby mi to někdo zkouknul a zkontroloval, byl bych rád :o). Předem díky :o)
[5] (Pavel Šindelka) - 16. 03. 2008, 14:31:32
ad [4] .. Jednak je nutné se přesvědčit, že hosting, kde se projekt nachází, podporuje používání vlastního souboru .htaccess. Poté bych použil pravidlo ve stylu:

RewriteEngine on
RewriteRule .*Data.*\.jpg$ /index.php

Nicméně je tu ten problém, že se k těmto souborům pak nedostane žádný request tohoto tvaru, tj. ani vlastní stránky (pro jednotlivé obrázky na stránce jsou defacto generovány jednotlivé zvláštní dotazy na server). Pro zamezení přístupu "zvenčí" je pak nutné použít jiných metod (namátkou například RewriteCond a jeho proměnnou %{HTTP_REFERER}).

Komentovat


Tento článek byl uzavřen. Už není možné k němu přidávat komentáře ani hlasovat