(ne)kanonizace lomítek v URL

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Elijen
Člen | 171
+
0
-

Narazil jsem na takovou osklivost v routovani:

Routa:

$frontRoutes[] = new Route('<city>/<category>', 'Homepage:default');

Matchujici url:

"http://example.com/mesto/kategorie"        //OK - kanonicka
"http://example.com/mesto/kategorie/"       //OK - presmeruje na kanonickou
"http://example.com////mesto/kategorie/"    //OK - matchuje a presmeruje na kanonickou (i kdyz by teoreticky mohlo hodit 404)
"http://example.com////mesto/kategorie"     //FAIL - matchuje ale nepresmeruje na kanonickou (resp. nehodi 404)
"http://example.com////mesto/////kategorie" //FAIL - stejny pripad jako vyse

Ocividne Nette URL kanonizovat umi, ale v pripade, ze na konci neni lomitko se o to nepokousi, lenoch! :-) Da se toto vyresit na strane aplikace (jinak nez implementovanim IRoute) nebo je to chyba ve Frameworku?

Zkousel jsem v Nette 0.9, 2.0 beta i 2.0 stable.

Editoval Elijen (14. 2. 2012 17:15)

frosty22
Člen | 373
+
0
-

Pravda nyní jsem zkusil na několika projektech a je to to samé, v podstatě je to i zde:

<?php
https://nette.org/cs/packages
?>

Co se týče BadRequestException VS kanonizace, tak bych se asi též přikláněl k 404ce, jelikož u výchozí routy např:

<?php
<presenter>/<action>
?>

bych logicky při URL:

http://www.example.com//test

očekával, že presenter je null/empty než-li zkanonizovat.

Dokonce jsem tedy i našel již téma, kde to řešilo, a prý se to bude řešit?
https://forum.nette.org/…obna-lomitka

Editoval frosty22 (14. 2. 2012 17:14)

frosty22
Člen | 373
+
0
-

Hledal jsem jádro problému a nalezl jsem ho v RequestFactory, kde je přímo uveden filter, který odstraňuje vícenásobná lomítka:

https://api.nette.org/…ory.php.html#31

29:     /** @var array */
30:     public $urlFilters = array(
31:         'path' => array('#/{2,}#' => '/'), // '%20' => ''
32:         'url' => array(), // '#[.,)]$#' => ''
33:     );

Tento je tedy přímo odstraní z requestu, tudíž se vždy routa matchne jako korektní, při odstranění filtru je vyhozen BadRequest, což by mohlo být korektní .. avšak jistě ten filtr zde bude mít nějaké opodstatnění, bohužel mě zatím nenapadá jaké ;(

Editoval frosty22 (16. 2. 2012 11:43)

frosty22
Člen | 373
+
0
-

Stále nikdo nic? Takže to nikoho netrápí a nebo nikdo neví? :(

Filip Procházka
Moderator | 4668
+
0
-

Nikoho to netrápí. Jaktože to nevidím v https://github.com/…nette/issues ?

frosty22
Člen | 373
+
0
-

Asi protože jsem to tam nedal? :) Nezakládal jsem to jako problém, jelikož jsem prvotně očekával vyjádření zde, zda to řešit či neřešit.

frosty22
Člen | 373
+
0
-

A neví tedy někdo k čemu je tam napsán onen filtr výše pro odstranění oněch lomítek, případně pokud se dá pryč, tak to začne fungovat, avšak nejsem si jist zdali to nemá dopad na něco jiného – předpokládám, že asi ano, jinak by tam byl zbytečně :)

David Grudl
Nette Core | 8218
+
0
-

Věc se má tak, že filtrování URL probíhá na nejnižší vrstvě, proto Presenter už pracuje s upravenou URL a nepřesměruje. Což sice není úplně ideální, ale jde o vcelku nepodstatnou věc, že se mi to nikdy nechtělo řešit.

frosty22
Člen | 373
+
0
-

Je pravda, že v praxi se to asi neprojeví, že by vznikly duplicitní URL, to by muselo být cílené, čili otázka zní, zdali tedy by nebylo jednodušší to řešit na straně htaccessu jelikož kromě hodnot parametrů v query stringu, nemají v URL vícenásobná lomítka opodstatnění.

Elijen
Člen | 171
+
0
-

URL se korektne kanonizuje (odstrani se duplicitni lomitka) v pripade, ze konci lomitkem. Z toho bych soudil, ze oprava by mohla byt trivialni ⇒ kanonizovat URL i v pripade, ze nekonci lomitkem.

Zatim se mi ale nepodarilo poradne vykoumat kde se toto deje … takze to mozna nebude az tak trivialni :-D

Editoval Elijen (29. 2. 2012 23:36)

David Grudl
Nette Core | 8218
+
0
-

To nesouvisí s tím, jestli to končí lomítkem, ale s tím, že znásobené lomítka se jednoduše nepřesměrovávají. Pokud se přesměruje, tak to je z jiného důvodu, než že tam jsou znásobená lomítka.

frosty22
Člen | 373
+
0
-

No jak psal David, tak URL se předá do HttpRequestFactory, kde se rozdělí na jednotlivé části a právě zde dojde k onomu odstranění násobných lomítek díky onomu regulárnímu výrazu (viz výše), a poté se již tyto části předají routování, které matchne danou URL a zavolá korektní presenter. V případě, že však je lomítko na konci/není, tak to je součást URL i v tuto chvíli, a dle rout se poté buď přesměruje na URL s lomítkem či bez. Zároveň se i znovu složí URL z těch částí (kromě defaultních) a pokud se tyto části neshodují s příchozí URL, tj. obsahují defaultní parametr, tak se přesměruje na onu kanonickou URL.

No asi jsem to podal trošku nesrozumitelně, ale špatně se to vysvětluje. Ale ve finále je tedy problém, v onom převedení URL na její části. Při odstranění onoho filtru na vícenásobná lomítka z HttpRequestFactory se problém vyřeší (a asi i bez jiných následků), ale spíše je otázka, zda-li by objekt, který zpracovává URL na její části by se měl takto chovat, že je zachová. Takže logičtější by asi bylo, kdyby ještě obsahoval validaci URL, metodu isValid() ? a poté by se při před předáním HttpRequestFactory vracel i stav, zda-li je korektní URL a pokud ne, tak přesměrovat na 404.

Oproti tomuto však vícenásobná lomítka v URL nejsou nevalidní, jen spíše nežádaná, takže hlavní problém asi tkví v tom, v jaké fázi toto řešit. Opravdu asi zatím se mi jeví jako nejsympatičtější to řešit v .htaccessu.