diff --git a/Classes/Exceptions/Http/Exception.php b/Classes/Exceptions/Http/Exception.php new file mode 100644 index 0000000..e7ae67c --- /dev/null +++ b/Classes/Exceptions/Http/Exception.php @@ -0,0 +1,20 @@ +statusCode = $statusCode; + } +} diff --git a/Classes/RoutingMiddleware.php b/Classes/RoutingMiddleware.php index 5ab9047..458c7b5 100644 --- a/Classes/RoutingMiddleware.php +++ b/Classes/RoutingMiddleware.php @@ -5,6 +5,7 @@ namespace Flowpack\SeoRouting; use Flowpack\SeoRouting\Enum\TrailingSlashModeEnum; +use Flowpack\SeoRouting\Exceptions\Http\Exception as HttpException; use Flowpack\SeoRouting\Helper\BlocklistHelper; use Flowpack\SeoRouting\Helper\ConfigurationHelper; use Flowpack\SeoRouting\Helper\LowerCaseHelper; @@ -33,6 +34,9 @@ class RoutingMiddleware implements MiddlewareInterface #[Flow\Inject] protected LowerCaseHelper $lowerCaseHelper; + /** + * @throws HttpException + */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $isTrailingSlashEnabled = $this->configurationHelper->isTrailingSlashEnabled(); @@ -61,17 +65,19 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $uri = $this->lowerCaseHelper->convertPathToLowerCase($uri); } - if ($uri->getPath() === $oldPath) { - return $handler->handle($request); + $response = $handler->handle($request); + + if ($uri->getPath() === $oldPath || $response->getStatusCode() >= 400) { + return $response; } - $response = $handler->handle($request); + $statusCode = $this->configurationHelper->getStatusCode(); - if ($response->getStatusCode() >= 400) { - return $response; + if ($statusCode >= 400) { + throw new HttpException($statusCode); } - return $this->responseFactory->createResponse($this->configurationHelper->getStatusCode()) + return $this->responseFactory->createResponse($statusCode) ->withAddedHeader('Location', (string)$uri); } } diff --git a/Tests/Unit/RoutingMiddlewareTest.php b/Tests/Unit/RoutingMiddlewareTest.php index cd80865..2a6fc81 100644 --- a/Tests/Unit/RoutingMiddlewareTest.php +++ b/Tests/Unit/RoutingMiddlewareTest.php @@ -5,6 +5,7 @@ namespace Flowpack\SeoRouting\Tests\Unit; use Flowpack\SeoRouting\Enum\TrailingSlashModeEnum; +use Flowpack\SeoRouting\Exceptions\Http\Exception as HttpException; use Flowpack\SeoRouting\Helper\BlocklistHelper; use Flowpack\SeoRouting\Helper\ConfigurationHelper; use Flowpack\SeoRouting\Helper\LowerCaseHelper; @@ -21,8 +22,10 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use ReflectionClass; +use Throwable; #[CoversClass(RoutingMiddleware::class)] +#[CoversClass(HttpException::class)] class RoutingMiddlewareTest extends TestCase { private readonly RoutingMiddleware $routingMiddleware; @@ -72,6 +75,11 @@ protected function setUp(): void } + /** + * @param class-string|null $expectedException + * @throws Exception + * @throws HttpException + */ #[DataProvider('urlsDataProvider')] public function testProcessShouldHandleUrlsCorrectly( string $originalUrl, @@ -82,6 +90,7 @@ public function testProcessShouldHandleUrlsCorrectly( int $statusCode, TrailingSlashModeEnum $trailingSlashMode, int $handlerStatusCode = 200, + ?string $expectedException = null, ): void { $originalUri = new Uri($originalUrl); $expectedUri = new Uri($expectedUrl); @@ -98,8 +107,12 @@ public function testProcessShouldHandleUrlsCorrectly( $this->requestMock->expects($this->once())->method('getUri')->willReturn($originalUri); $pathChanged = $originalUrl !== $expectedUrl; - - if (!$pathChanged) { + if (is_string($expectedException)) { + $this->expectException($expectedException); + $this->responseFactoryMock->expects($this->never())->method('createResponse'); + $this->routingMiddleware->process($this->requestMock, $this->requestHandlerMock); + return; + } elseif (!$pathChanged) { $this->requestHandlerMock->method('handle')->willReturn($this->responseMock); } elseif ($handlerStatusCode >= 400) { $this->responseMock->method('getStatusCode')->willReturn($handlerStatusCode); @@ -122,7 +135,6 @@ public function testProcessShouldHandleUrlsCorrectly( ->with('Location', (string)$expectedUri) ->willReturnSelf(); } - self::assertSame( $this->responseMock, $this->routingMiddleware->process($this->requestMock, $this->requestHandlerMock) @@ -190,6 +202,16 @@ public static function urlsDataProvider(): array 'trailingSlashMode' => TrailingSlashModeEnum::ADD, 'handlerStatusCode' => 404, ], + [ + 'originalUrl' => 'https://local.dev', + 'expectedUrl' => 'https://local.dev/', + 'isTrailingSlashEnabledResult' => true, + 'isToLowerCaseEnabledResult' => false, + 'isUriInBlocklistResult' => false, + 'statusCode' => 404, + 'trailingSlashMode' => TrailingSlashModeEnum::ADD, + 'expectedException' => HttpException::class + ], ]; } }