diff --git a/src/MethodFailureHandler/MethodFailureHandlerInterface.php b/src/MethodFailureHandler/MethodFailureHandlerInterface.php new file mode 100644 index 00000000..94067039 --- /dev/null +++ b/src/MethodFailureHandler/MethodFailureHandlerInterface.php @@ -0,0 +1,16 @@ +getMethod() === Method::OPTIONS + ? $this->createAllowedMethodsResponse($allowedMethods) + : $this->createMethodNotAllowedResponse($allowedMethods); + } + + /** + * @param string[] $allowedMethods + */ + private function createAllowedMethodsResponse(array $allowedMethods): ResponseInterface + { + return $this->responseFactory + ->createResponse(Status::NO_CONTENT) + ->withHeader(Header::ALLOW, implode(', ', $allowedMethods)); + } + + /** + * @param string[] $allowedMethods + */ + private function createMethodNotAllowedResponse(array $allowedMethods): ResponseInterface + { + return $this->responseFactory + ->createResponse(Status::METHOD_NOT_ALLOWED) + ->withHeader(Header::ALLOW, implode(', ', $allowedMethods)); + } +} diff --git a/src/Middleware/Router.php b/src/Middleware/Router.php index 78d130cb..2f483612 100644 --- a/src/Middleware/Router.php +++ b/src/Middleware/Router.php @@ -10,25 +10,30 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -use Yiisoft\Http\Method; -use Yiisoft\Http\Status; use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher; use Yiisoft\Middleware\Dispatcher\MiddlewareFactory; use Yiisoft\Router\CurrentRoute; +use Yiisoft\Router\MethodFailureHandler\StandardMethodFailureHandler; +use Yiisoft\Router\MethodFailureHandler\MethodFailureHandlerInterface; use Yiisoft\Router\UrlMatcherInterface; final class Router implements MiddlewareInterface { private readonly MiddlewareDispatcher $dispatcher; + private readonly MethodFailureHandlerInterface|null $methodFailureHandler; public function __construct( private readonly UrlMatcherInterface $matcher, - private readonly ResponseFactoryInterface $responseFactory, + ResponseFactoryInterface $responseFactory, MiddlewareFactory $middlewareFactory, private readonly CurrentRoute $currentRoute, - ?EventDispatcherInterface $eventDispatcher = null + ?EventDispatcherInterface $eventDispatcher = null, + MethodFailureHandlerInterface|false|null $methodFailureHandler = null, ) { $this->dispatcher = new MiddlewareDispatcher($middlewareFactory, $eventDispatcher); + $this->methodFailureHandler = $methodFailureHandler === false + ? null + : $methodFailureHandler ?? new StandardMethodFailureHandler($responseFactory); } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface @@ -37,15 +42,8 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $this->currentRoute->setUri($request->getUri()); - if ($result->isMethodFailure()) { - if ($request->getMethod() === Method::OPTIONS) { - return $this->responseFactory - ->createResponse(Status::NO_CONTENT) - ->withHeader('Allow', implode(', ', $result->methods())); - } - return $this->responseFactory - ->createResponse(Status::METHOD_NOT_ALLOWED) - ->withHeader('Allow', implode(', ', $result->methods())); + if ($result->isMethodFailure() && $this->methodFailureHandler !== null) { + return $this->methodFailureHandler->handle($request, $result->methods()); } if (!$result->isSuccess()) {