From e6a29c747662e1f646859bfec16a2f1361371ab9 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 13 Mar 2024 14:22:44 +0100 Subject: [PATCH] fix: handle encoded slashes for url parameters - fixes #552 --- flight/net/Route.php | 13 ++++++++++--- flight/net/Router.php | 3 +-- tests/RouterTest.php | 12 +++++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/flight/net/Route.php b/flight/net/Route.php index 22c3cf0..4abf2ae 100644 --- a/flight/net/Route.php +++ b/flight/net/Route.php @@ -97,7 +97,7 @@ class Route /** * Checks if a URL matches the route pattern. Also parses named parameters in the URL. * - * @param string $url Requested URL + * @param string $url Requested URL (original format, not URL decoded) * @param bool $case_sensitive Case sensitive matching * * @return bool Match status @@ -127,11 +127,18 @@ class Route } } - $this->splat = strval(substr($url, $i + 1)); + $this->splat = urldecode(strval(substr($url, $i + 1))); } // Build the regex for matching - $regex = str_replace([')', '/*'], [')?', '(/?|/.*?)'], $this->pattern); + $pattern_utf_chars_encoded = preg_replace_callback( + '#(\\p{L}+)#u', + static function ($matches) { + return urlencode($matches[0]); + }, + $this->pattern + ); + $regex = str_replace([')', '/*'], [')?', '(/?|/.*?)'], $pattern_utf_chars_encoded); $regex = preg_replace_callback( '#@([\w]+)(:([^/\(\)]*))?#', diff --git a/flight/net/Router.php b/flight/net/Router.php index 346a791..f739a24 100644 --- a/flight/net/Router.php +++ b/flight/net/Router.php @@ -215,9 +215,8 @@ class Router */ public function route(Request $request) { - $url_decoded = urldecode($request->url); while ($route = $this->current()) { - if ($route->matchMethod($request->method) && $route->matchUrl($url_decoded, $this->case_sensitive)) { + if ($route->matchMethod($request->method) && $route->matchUrl($request->url, $this->case_sensitive)) { $this->executedRoute = $route; return $route; } diff --git a/tests/RouterTest.php b/tests/RouterTest.php index 1b52ae1..8ed272e 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -198,6 +198,16 @@ class RouterTest extends TestCase $this->check('123'); } + public function testUrlParametersWithEncodedSlash() + { + $this->router->map('/redirect/@id', function ($id) { + echo $id; + }); + $this->request->url = '/redirect/before%2Fafter'; + + $this->check('before/after'); + } + // Passing URL parameters matched with regular expression public function testRegExParameters() { @@ -390,7 +400,7 @@ class RouterTest extends TestCase $this->router->map('/категория/@name:[абвгдеёжзийклмнопрстуфхцчшщъыьэюя]+', function ($name) { echo $name; }); - $this->request->url = urlencode('/категория/цветя'); + $this->request->url = '/' . urlencode('категория') . '/' . urlencode('цветя'); $this->check('цветя'); }