Account for trailing slashes in URLs.
This commit is contained in:
parent
2bb9cccf18
commit
2372a113d2
5 changed files with 20 additions and 9 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
0.2503.230337
|
||||
0.2503.230355
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
// PatternFilter.php
|
||||
// Created: 2024-03-28
|
||||
// Updated: 2025-03-07
|
||||
// Updated: 2025-03-23
|
||||
|
||||
namespace Index\Http\Routing\Filters;
|
||||
|
||||
|
@ -18,14 +18,14 @@ class PatternFilter extends FilterAttribute {
|
|||
/**
|
||||
* @param string $pattern URI path pattern.
|
||||
* @param bool $raw If true, $pattern is taken as is, if false, $pattern is prefixed with #^ and suffixed with #u or $#uD
|
||||
* @param bool $prefix Only has effect if $raw is false. If true is #u appended to $pattern, otherwise $#uD.
|
||||
* @param bool $prefix Only has effect if $raw is false. If true is #u appended to $pattern, otherwise /?$#uD.
|
||||
*/
|
||||
public function __construct(
|
||||
string $pattern,
|
||||
bool $raw = false,
|
||||
bool $prefix = true,
|
||||
) {
|
||||
$this->pattern = $raw ? $pattern : sprintf('#^%s%s', $pattern, $prefix ? '#u' : '$#uD');
|
||||
$this->pattern = $raw ? $pattern : sprintf('#^%s%s', $pattern, $prefix ? '#u' : '/?$#uD');
|
||||
}
|
||||
|
||||
public function createInstance(Closure $handler): FilterInfo {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
// PatternRoute.php
|
||||
// Created: 2024-03-28
|
||||
// Updated: 2025-03-07
|
||||
// Updated: 2025-03-23
|
||||
|
||||
namespace Index\Http\Routing\Routes;
|
||||
|
||||
|
@ -19,13 +19,15 @@ class PatternRoute extends RouteAttribute {
|
|||
* @param string $method HTTP Method.
|
||||
* @param string $pattern URI path pattern.
|
||||
* @param bool $raw If true, $pattern is taken as is, if false, $pattern is prefixed with #^ and suffixed with $#uD
|
||||
* @param bool $slash Only has effect if $raw is false. If true /? is appended to $pattern to allow for trailing slashes.
|
||||
*/
|
||||
public function __construct(
|
||||
private string $method,
|
||||
string $pattern,
|
||||
bool $raw = false
|
||||
bool $raw = false,
|
||||
bool $slash = true,
|
||||
) {
|
||||
$this->pattern = $raw ? $pattern : sprintf('#^%s$#uD', $pattern);
|
||||
$this->pattern = $raw ? $pattern : sprintf('#^%s%s$#uD', $pattern, $slash ? '/?' : '');
|
||||
}
|
||||
|
||||
public function createInstance(Closure $handler): RouteInfo {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
// ExactPathUriMatcher.php
|
||||
// Created: 2025-03-07
|
||||
// Updated: 2025-03-07
|
||||
// Updated: 2025-03-23
|
||||
|
||||
namespace Index\Http\Routing\UriMatchers;
|
||||
|
||||
|
@ -19,6 +19,7 @@ class ExactPathUriMatcher implements UriMatcher {
|
|||
) {}
|
||||
|
||||
public function match(UriInterface $uri): array|bool {
|
||||
return $uri->getPath() === $this->path;
|
||||
$path = $uri->getPath();
|
||||
return $path === $this->path || $path === ($this->path . '/');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,12 @@ final class RouterTest extends TestCase {
|
|||
return 'hit pattern';
|
||||
}
|
||||
|
||||
#[ExactRoute('GET', '/assets/avatar')]
|
||||
#[PatternRoute('GET', '/assets/avatar/([0-9]+)(?:\.[a-z]+)?')]
|
||||
public function getTrailingSlash(): string {
|
||||
return 'hit';
|
||||
}
|
||||
|
||||
public function hasNoAttr(): string {
|
||||
return 'not a route';
|
||||
}
|
||||
|
@ -163,6 +169,8 @@ final class RouterTest extends TestCase {
|
|||
$this->assertSame('1RJNSRYmxrvXUr////jpg', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/uploads/1RJNSRYmxrvXUr.jpg'))->getBody());
|
||||
$this->assertSame('hit exact', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/messages/stats'))->getBody());
|
||||
$this->assertSame('hit pattern', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/messages/soaps'))->getBody());
|
||||
$this->assertSame('hit', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/assets/avatar/'))->getBody());
|
||||
$this->assertSame('hit', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/assets/avatar/123/'))->getBody());
|
||||
}
|
||||
|
||||
public function testEEPROMSituation(): void {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue