Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Classes/Exceptions/Http/Exception.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Flowpack\SeoRouting\Exceptions\Http;

use Throwable;

/**
* An exception where the HTTP status code can be set.
*/
class Exception extends \Neos\Flow\Http\Exception
{
public function __construct(int $statusCode, string $message = "", int $code = 0, ?Throwable $previous = null)
{
parent::__construct($message, $code, $previous);

$this->statusCode = $statusCode;
}
}
18 changes: 12 additions & 6 deletions Classes/RoutingMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
}
28 changes: 25 additions & 3 deletions Tests/Unit/RoutingMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -72,6 +75,11 @@ protected function setUp(): void
}


/**
* @param class-string<Throwable>|null $expectedException
* @throws Exception
* @throws HttpException
*/
#[DataProvider('urlsDataProvider')]
public function testProcessShouldHandleUrlsCorrectly(
string $originalUrl,
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -122,7 +135,6 @@ public function testProcessShouldHandleUrlsCorrectly(
->with('Location', (string)$expectedUri)
->willReturnSelf();
}

self::assertSame(
$this->responseMock,
$this->routingMiddleware->process($this->requestMock, $this->requestHandlerMock)
Expand Down Expand Up @@ -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
],
];
}
}
Loading