Fixed multiple trailing slashes issues. Also fixed server test for 405 and 404

pull/618/head
n0nag0n 1 week ago
parent 9d71303384
commit f4f3c7a342

@ -179,7 +179,7 @@ class Engine
} }
// Set case-sensitivity // Set case-sensitivity
$self->router()->case_sensitive = $self->get('flight.case_sensitive'); $self->router()->caseSensitive = $self->get('flight.case_sensitive');
// Set Content-Length // Set Content-Length
$self->response()->content_length = $self->get('flight.content_length'); $self->response()->content_length = $self->get('flight.content_length');
// This is to maintain legacy handling of output buffering // This is to maintain legacy handling of output buffering

@ -98,17 +98,24 @@ class Route
* Checks if a URL matches the route pattern. Also parses named parameters in the URL. * Checks if a URL matches the route pattern. Also parses named parameters in the URL.
* *
* @param string $url Requested URL (original format, not URL decoded) * @param string $url Requested URL (original format, not URL decoded)
* @param bool $case_sensitive Case sensitive matching * @param bool $caseSensitive Case sensitive matching
* *
* @return bool Match status * @return bool Match status
*/ */
public function matchUrl(string $url, bool $case_sensitive = false): bool public function matchUrl(string $url, bool $caseSensitive = false): bool
{ {
// Wildcard or exact match // Wildcard or exact match
if ($this->pattern === '*' || $this->pattern === $url) { if ($this->pattern === '*' || $this->pattern === $url) {
return true; return true;
} }
// if the last character of the incoming url is a slash, only allow one trailing slash, not multiple
if (substr($url, -2) === '//') {
// remove all trailing slashes, and then add one back.
$url = rtrim($url, '/') . '/';
}
$ids = []; $ids = [];
$last_char = substr($this->pattern, -1); $last_char = substr($this->pattern, -1);
@ -157,7 +164,7 @@ class Route
$regex .= $last_char === '/' ? '?' : '/?'; $regex .= $last_char === '/' ? '?' : '/?';
// Attempt to match route and named parameters // Attempt to match route and named parameters
if (!preg_match('#^' . $regex . '(?:\?[\s\S]*)?$#' . (($case_sensitive) ? '' : 'i'), $url, $matches)) { if (!preg_match('#^' . $regex . '(?:\?[\s\S]*)?$#' . (($caseSensitive) ? '' : 'i'), $url, $matches)) {
return false; return false;
} }

@ -20,7 +20,7 @@ class Router
/** /**
* Case sensitive matching. * Case sensitive matching.
*/ */
public bool $case_sensitive = false; public bool $caseSensitive = false;
/** /**
* Mapped routes. * Mapped routes.
@ -221,7 +221,7 @@ class Router
public function route(Request $request) public function route(Request $request)
{ {
while ($route = $this->current()) { while ($route = $this->current()) {
$urlMatches = $route->matchUrl($request->url, $this->case_sensitive); $urlMatches = $route->matchUrl($request->url, $this->caseSensitive);
$methodMatches = $route->matchMethod($request->method); $methodMatches = $route->matchMethod($request->method);
if ($urlMatches === true && $methodMatches === true) { if ($urlMatches === true && $methodMatches === true) {
$this->executedRoute = $route; $this->executedRoute = $route;

@ -45,7 +45,7 @@ class EngineTest extends TestCase
$engine->request()->url = '/someRoute'; $engine->request()->url = '/someRoute';
$engine->start(); $engine->start();
$this->assertFalse($engine->router()->case_sensitive); $this->assertFalse($engine->router()->caseSensitive);
$this->assertTrue($engine->response()->content_length); $this->assertTrue($engine->response()->content_length);
} }
@ -64,7 +64,7 @@ class EngineTest extends TestCase
// This is a necessary evil because of how the v2 output buffer works. // This is a necessary evil because of how the v2 output buffer works.
ob_end_clean(); ob_end_clean();
$this->assertFalse($engine->router()->case_sensitive); $this->assertFalse($engine->router()->caseSensitive);
$this->assertTrue($engine->response()->content_length); $this->assertTrue($engine->response()->content_length);
} }

@ -117,6 +117,14 @@ class RouterTest extends TestCase
$this->check('OK'); $this->check('OK');
} }
public function testPathRouteWithUrlTrailingSlash()
{
$this->router->map('/path', [$this, 'ok']);
$this->request->url = '/path/';
$this->check('OK');
}
public function testGetRouteShortcut() public function testGetRouteShortcut()
{ {
$this->router->get('/path', [$this, 'ok']); $this->router->get('/path', [$this, 'ok']);
@ -455,7 +463,7 @@ class RouterTest extends TestCase
{ {
$this->router->map('/hello', [$this, 'ok']); $this->router->map('/hello', [$this, 'ok']);
$this->request->url = '/HELLO'; $this->request->url = '/HELLO';
$this->router->case_sensitive = true; $this->router->caseSensitive = true;
$this->check('404'); $this->check('404');
} }
@ -752,4 +760,12 @@ class RouterTest extends TestCase
$this->assertEquals('/path1/123/abc', $url); $this->assertEquals('/path1/123/abc', $url);
} }
public function testStripMultipleSlashesFromUrlAndStillMatch()
{
$this->router->get('/', [ $this, 'ok' ]);
$this->request->url = '///';
$this->request->method = 'GET';
$this->check('OK');
}
} }

@ -71,7 +71,7 @@ Flight::post('/post', function () {})->addMiddleware(function() {});
Flight::delete('/delete', function () {}); Flight::delete('/delete', function () {});
Flight::put('/put', function () {}); Flight::put('/put', function () {});
Flight::patch('/patch', function () {})->addMiddleware('SomeMiddleware'); Flight::patch('/patch', function () {})->addMiddleware('SomeMiddleware');
Flight::router()->case_sensitive = true; Flight::router()->caseSensitive = true;
Flight::start(); Flight::start();
PHP; PHP;

@ -69,7 +69,8 @@ class LayoutMiddleware
<li><a href="/protected">Protected path</a></li> <li><a href="/protected">Protected path</a></li>
<li><a href="/template/templatevariable">Template path</a></li> <li><a href="/template/templatevariable">Template path</a></li>
<li><a href="/querytestpath?test=1&variable2=uuid&variable3=tester">Query path</a></li> <li><a href="/querytestpath?test=1&variable2=uuid&variable3=tester">Query path</a></li>
<li><a href="/postpage">404 Not Found</a></li> <li><a href="/badpagename">404 Not Found</a></li>
<li><a href="/postpage">405 Method Not Found</a></li>
<li><a href="{$final_route}">Mega group</a></li> <li><a href="{$final_route}">Mega group</a></li>
<li><a href="/error">Error</a></li> <li><a href="/error">Error</a></li>
<li><a href="/json">JSON</a></li> <li><a href="/json">JSON</a></li>

Loading…
Cancel
Save