Skip to content

Commit da6540b

Browse files
authored
Merge pull request #618 from flightphp/multiple-trailing-slashes
Fixed multiple trailing slashes issues.
2 parents 9d71303 + f4f3c7a commit da6540b

File tree

7 files changed

+35
-11
lines changed

7 files changed

+35
-11
lines changed

flight/Engine.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public function init(): void
179179
}
180180

181181
// Set case-sensitivity
182-
$self->router()->case_sensitive = $self->get('flight.case_sensitive');
182+
$self->router()->caseSensitive = $self->get('flight.case_sensitive');
183183
// Set Content-Length
184184
$self->response()->content_length = $self->get('flight.content_length');
185185
// This is to maintain legacy handling of output buffering

flight/net/Route.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,24 @@ public function __construct(string $pattern, $callback, array $methods, bool $pa
9898
* Checks if a URL matches the route pattern. Also parses named parameters in the URL.
9999
*
100100
* @param string $url Requested URL (original format, not URL decoded)
101-
* @param bool $case_sensitive Case sensitive matching
101+
* @param bool $caseSensitive Case sensitive matching
102102
*
103103
* @return bool Match status
104104
*/
105-
public function matchUrl(string $url, bool $case_sensitive = false): bool
105+
public function matchUrl(string $url, bool $caseSensitive = false): bool
106106
{
107107
// Wildcard or exact match
108108
if ($this->pattern === '*' || $this->pattern === $url) {
109109
return true;
110110
}
111111

112+
// if the last character of the incoming url is a slash, only allow one trailing slash, not multiple
113+
if (substr($url, -2) === '//') {
114+
// remove all trailing slashes, and then add one back.
115+
$url = rtrim($url, '/') . '/';
116+
}
117+
118+
112119
$ids = [];
113120
$last_char = substr($this->pattern, -1);
114121

@@ -157,7 +164,7 @@ static function ($matches) use (&$ids) {
157164
$regex .= $last_char === '/' ? '?' : '/?';
158165

159166
// Attempt to match route and named parameters
160-
if (!preg_match('#^' . $regex . '(?:\?[\s\S]*)?$#' . (($case_sensitive) ? '' : 'i'), $url, $matches)) {
167+
if (!preg_match('#^' . $regex . '(?:\?[\s\S]*)?$#' . (($caseSensitive) ? '' : 'i'), $url, $matches)) {
161168
return false;
162169
}
163170

flight/net/Router.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Router
2020
/**
2121
* Case sensitive matching.
2222
*/
23-
public bool $case_sensitive = false;
23+
public bool $caseSensitive = false;
2424

2525
/**
2626
* Mapped routes.
@@ -221,7 +221,7 @@ public function group(string $groupPrefix, callable $callback, array $groupMiddl
221221
public function route(Request $request)
222222
{
223223
while ($route = $this->current()) {
224-
$urlMatches = $route->matchUrl($request->url, $this->case_sensitive);
224+
$urlMatches = $route->matchUrl($request->url, $this->caseSensitive);
225225
$methodMatches = $route->matchMethod($request->method);
226226
if ($urlMatches === true && $methodMatches === true) {
227227
$this->executedRoute = $route;

tests/EngineTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function getInitializedVar()
4545
$engine->request()->url = '/someRoute';
4646
$engine->start();
4747

48-
$this->assertFalse($engine->router()->case_sensitive);
48+
$this->assertFalse($engine->router()->caseSensitive);
4949
$this->assertTrue($engine->response()->content_length);
5050
}
5151

@@ -64,7 +64,7 @@ public function getInitializedVar()
6464
// This is a necessary evil because of how the v2 output buffer works.
6565
ob_end_clean();
6666

67-
$this->assertFalse($engine->router()->case_sensitive);
67+
$this->assertFalse($engine->router()->caseSensitive);
6868
$this->assertTrue($engine->response()->content_length);
6969
}
7070

tests/RouterTest.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ public function testPathRouteTrailingSlash()
117117
$this->check('OK');
118118
}
119119

120+
public function testPathRouteWithUrlTrailingSlash()
121+
{
122+
$this->router->map('/path', [$this, 'ok']);
123+
$this->request->url = '/path/';
124+
125+
$this->check('OK');
126+
}
127+
120128
public function testGetRouteShortcut()
121129
{
122130
$this->router->get('/path', [$this, 'ok']);
@@ -455,7 +463,7 @@ public function testCaseSensitivity()
455463
{
456464
$this->router->map('/hello', [$this, 'ok']);
457465
$this->request->url = '/HELLO';
458-
$this->router->case_sensitive = true;
466+
$this->router->caseSensitive = true;
459467

460468
$this->check('404');
461469
}
@@ -752,4 +760,12 @@ public function testGetUrlByAliasWithGroupSimpleParams()
752760

753761
$this->assertEquals('/path1/123/abc', $url);
754762
}
763+
764+
public function testStripMultipleSlashesFromUrlAndStillMatch()
765+
{
766+
$this->router->get('/', [ $this, 'ok' ]);
767+
$this->request->url = '///';
768+
$this->request->method = 'GET';
769+
$this->check('OK');
770+
}
755771
}

tests/commands/RouteCommandTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ protected function createIndexFile()
7171
Flight::delete('/delete', function () {});
7272
Flight::put('/put', function () {});
7373
Flight::patch('/patch', function () {})->addMiddleware('SomeMiddleware');
74-
Flight::router()->case_sensitive = true;
74+
Flight::router()->caseSensitive = true;
7575
7676
Flight::start();
7777
PHP;

tests/server/LayoutMiddleware.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ public function before()
6969
<li><a href="/protected">Protected path</a></li>
7070
<li><a href="/template/templatevariable">Template path</a></li>
7171
<li><a href="/querytestpath?test=1&variable2=uuid&variable3=tester">Query path</a></li>
72-
<li><a href="/postpage">404 Not Found</a></li>
72+
<li><a href="/badpagename">404 Not Found</a></li>
73+
<li><a href="/postpage">405 Method Not Found</a></li>
7374
<li><a href="{$final_route}">Mega group</a></li>
7475
<li><a href="/error">Error</a></li>
7576
<li><a href="/json">JSON</a></li>

0 commit comments

Comments
 (0)