diff --git a/src/Middleware/ImplicitOptionsMiddleware.php b/src/Middleware/ImplicitOptionsMiddleware.php index e19247e..04051b2 100644 --- a/src/Middleware/ImplicitOptionsMiddleware.php +++ b/src/Middleware/ImplicitOptionsMiddleware.php @@ -75,6 +75,10 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return $handler->handle($request); } + if ($result->isFailure() && ! $result->isMethodFailure()) { + return $handler->handle($request); + } + if ($result->getMatchedRoute()) { return $handler->handle($request); } diff --git a/src/Test/ImplicitMethodsIntegrationTest.php b/src/Test/ImplicitMethodsIntegrationTest.php index 5963169..822de16 100644 --- a/src/Test/ImplicitMethodsIntegrationTest.php +++ b/src/Test/ImplicitMethodsIntegrationTest.php @@ -363,4 +363,51 @@ public function testImplicitOptionsRequest( $this->assertSame($finalResponse->reveal(), $response); } + + public function testImplicitOptionsRequestRouteNotFound() + { + $router = $this->getRouter(); + + $pipeline = new MiddlewarePipe(); + $pipeline->pipe(new RouteMiddleware($router)); + $pipeline->pipe($this->getImplicitOptionsMiddleware()); + $pipeline->pipe(new MethodNotAllowedMiddleware($this->createInvalidResponseFactory())); + $pipeline->pipe(new DispatchMiddleware()); + + $finalResponse = (new Response()) + ->withStatus(StatusCode::STATUS_IM_A_TEAPOT) + ->withHeader('foo-bar', 'baz'); + $finalResponse->getBody()->write('FOO BAR BODY'); + + $request = new ServerRequest( + ['REQUEST_METHOD' => RequestMethod::METHOD_OPTIONS], + [], + '/not-found', + RequestMethod::METHOD_OPTIONS + ); + + $finalHandler = $this->prophesize(RequestHandlerInterface::class); + $finalHandler + ->handle(Argument::that(function (ServerRequestInterface $request) { + Assert::assertSame(RequestMethod::METHOD_OPTIONS, $request->getMethod()); + + $routeResult = $request->getAttribute(RouteResult::class); + Assert::assertInstanceOf(RouteResult::class, $routeResult); + Assert::assertTrue($routeResult->isFailure()); + Assert::assertFalse($routeResult->isSuccess()); + Assert::assertFalse($routeResult->isMethodFailure()); + Assert::assertFalse($routeResult->getMatchedRoute()); + + return true; + })) + ->willReturn($finalResponse) + ->shouldBeCalledTimes(1); + + $response = $pipeline->process($request, $finalHandler->reveal()); + + $this->assertEquals(StatusCode::STATUS_IM_A_TEAPOT, $response->getStatusCode()); + $this->assertSame('FOO BAR BODY', (string) $response->getBody()); + $this->assertTrue($response->hasHeader('foo-bar')); + $this->assertSame('baz', $response->getHeaderLine('foo-bar')); + } } diff --git a/test/Middleware/ImplicitOptionsMiddlewareTest.php b/test/Middleware/ImplicitOptionsMiddlewareTest.php index 959ffcd..d2b9f38 100644 --- a/test/Middleware/ImplicitOptionsMiddlewareTest.php +++ b/test/Middleware/ImplicitOptionsMiddlewareTest.php @@ -73,12 +73,11 @@ public function testReturnsResultOfHandlerWhenRouteSupportsOptionsExplicitly() { $route = $this->prophesize(Route::class); - $result = $this->prophesize(RouteResult::class); - $result->getMatchedRoute()->will([$route, 'reveal']); + $result = RouteResult::fromRoute($route->reveal()); $request = $this->prophesize(ServerRequestInterface::class); $request->getMethod()->willReturn(RequestMethod::METHOD_OPTIONS); - $request->getAttribute(RouteResult::class)->will([$result, 'reveal']); + $request->getAttribute(RouteResult::class)->willReturn($result); $response = $this->prophesize(ResponseInterface::class)->reveal(); @@ -93,13 +92,11 @@ public function testInjectsAllowHeaderInResponseProvidedToConstructorDuringOptio { $allowedMethods = [RequestMethod::METHOD_GET, RequestMethod::METHOD_POST]; - $result = $this->prophesize(RouteResult::class); - $result->getAllowedMethods()->willReturn($allowedMethods); - $result->getMatchedRoute()->willReturn(false); + $result = RouteResult::fromRouteFailure($allowedMethods); $request = $this->prophesize(ServerRequestInterface::class); $request->getMethod()->willReturn(RequestMethod::METHOD_OPTIONS); - $request->getAttribute(RouteResult::class)->will([$result, 'reveal']); + $request->getAttribute(RouteResult::class)->willReturn($result); $handler = $this->prophesize(RequestHandlerInterface::class); $handler->handle($request->reveal())->shouldNotBeCalled(); @@ -111,4 +108,21 @@ public function testInjectsAllowHeaderInResponseProvidedToConstructorDuringOptio $result = $this->middleware->process($request->reveal(), $handler->reveal()); $this->assertSame($this->response->reveal(), $result); } + + public function testReturnsResultOfHandlerWhenRouteNotFound() + { + $result = RouteResult::fromRouteFailure(Route::HTTP_METHOD_ANY); + + $request = $this->prophesize(ServerRequestInterface::class); + $request->getMethod()->willReturn(RequestMethod::METHOD_OPTIONS); + $request->getAttribute(RouteResult::class)->willReturn($result); + + $response = $this->prophesize(ResponseInterface::class)->reveal(); + + $handler = $this->prophesize(RequestHandlerInterface::class); + $handler->handle($request->reveal())->willReturn($response); + + $result = $this->middleware->process($request->reveal(), $handler->reveal()); + $this->assertSame($response, $result); + } }