diff --git a/src/Routing/Router.php b/src/Routing/Router.php index 35bc5b9..bc705f7 100644 --- a/src/Routing/Router.php +++ b/src/Routing/Router.php @@ -6,6 +6,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use WellRESTed\Dispatching\Dispatcher; use WellRESTed\Dispatching\DispatcherInterface; +use WellRESTed\Message\Response; use WellRESTed\Routing\Route\RouteFactory; use WellRESTed\Routing\Route\RouteFactoryInterface; use WellRESTed\Routing\Route\RouteInterface; @@ -27,7 +28,9 @@ class Router implements RouterInterface /** @var RouteInterface[] Hash array mapping path prefixes to routes */ private $patternRoutes; /** @var mixed[] List array of middleware */ - protected $stack; + private $stack; + /** @var bool Call the next middleware when no route matches */ + private $continue = false; /** * Create a new Router. @@ -91,7 +94,10 @@ class Router implements RouterInterface } } - // If no route exists, delegate to the next middleware. + if (!$this->continue) { + return $response->withStatus(404); + } + return $next($request, $response); } @@ -173,6 +179,12 @@ class Router implements RouterInterface return $this; } + public function continue() + { + $this->continue = true; + return $this; + } + /** * Return an instance to dispatch middleware. * diff --git a/src/Server.php b/src/Server.php index cb2c0a3..5b2b485 100644 --- a/src/Server.php +++ b/src/Server.php @@ -28,8 +28,6 @@ class Server private $transmitter; /** @var mixed[] List array of middleware */ private $stack; - /** @var ResponseInterface */ - private $unhandledResponse; public function __construct() { $this->stack = []; @@ -75,8 +73,8 @@ class Server $response = $this->getResponse(); - $next = function () { - return $this->getUnhandledResponse(); + $next = function ($rqst, $resp) { + return $resp; }; $dispatcher = $this->getDispatcher(); @@ -149,15 +147,6 @@ class Server return $this; } - /** - * @param ResponseInterface $response - * @return Server - */ - public function setUnhandledResponse(ResponseInterface $response): Server { - $this->unhandledResponse = $response; - return $this; - } - // ------------------------------------------------------------------------- /* Defaults */ @@ -200,12 +189,4 @@ class Server } return $this->transmitter; } - - private function getUnhandledResponse() - { - if (!$this->unhandledResponse) { - $this->unhandledResponse = new Response(404); - } - return $this->unhandledResponse; - } } diff --git a/test/tests/integration/RoutingTest.php b/test/tests/integration/RoutingTest.php index 18818cd..be748f1 100644 --- a/test/tests/integration/RoutingTest.php +++ b/test/tests/integration/RoutingTest.php @@ -128,7 +128,8 @@ class RoutingTest extends TestCase ->addMiddleware(new HeaderAdderMiddleware( 'Content-type', 'application/cat')) ->register('GET', '/molly', new StringHandler('Molly')) - ->register('GET', '/oscar', new StringHandler('Oscar')); + ->register('GET', '/oscar', new StringHandler('Oscar')) + ->continue(); $this->server->add($catRouter); $dogRouter = $this->server->createRouter() @@ -154,7 +155,8 @@ class RoutingTest extends TestCase ->addMiddleware(new HeaderAdderMiddleware( 'Content-type', 'application/cat')) ->register('GET', '/molly', new StringHandler('Molly')) - ->register('GET', '/oscar', new StringHandler('Oscar')); + ->register('GET', '/oscar', new StringHandler('Oscar')) + ->continue(); $this->server->add($catRouter); $dogRouter = $this->server->createRouter() diff --git a/test/tests/unit/Routing/RouterTest.php b/test/tests/unit/Routing/RouterTest.php index c8a1145..c0810a2 100644 --- a/test/tests/unit/Routing/RouterTest.php +++ b/test/tests/unit/Routing/RouterTest.php @@ -361,9 +361,27 @@ class RouterTest extends TestCase )->shouldHaveBeenCalled(); } - public function testPropagatesToNextMiddlewareWhenNoRouteMatches() + // ------------------------------------------------------------------------ + // No Match + + public function testWhenNoRouteMatchesByDefaultResponds404() { $this->request = $this->request->withRequestTarget("/no/match"); + $response = $this->router->__invoke($this->request, $this->response, $this->next); + $this->assertEquals(404, $response->getStatusCode()); + } + + public function testWhenNoRouteMatchesByDefaultDoesNotPropagatesToNextMiddleware() + { + $this->request = $this->request->withRequestTarget("/no/match"); + $this->router->__invoke($this->request, $this->response, $this->next); + $this->assertFalse($this->next->called); + } + + public function testWhenNoRouteMatchesAndContinueModePropagatesToNextMiddleware() + { + $this->request = $this->request->withRequestTarget("/no/match"); + $this->router->continue(); $this->router->__invoke($this->request, $this->response, $this->next); $this->assertTrue($this->next->called); } diff --git a/test/tests/unit/ServerTest.php b/test/tests/unit/ServerTest.php index 4aed4d7..0ea2cba 100644 --- a/test/tests/unit/ServerTest.php +++ b/test/tests/unit/ServerTest.php @@ -182,36 +182,23 @@ class ServerTest extends TestCase // ------------------------------------------------------------------------- // End of Stack - public function testResponds404ByDefaultWhenReachingEndOfStack() + public function testReturnsLastDoublePassResponseAtEndOfStack() { - $this->server->respond(); + $defaultResponse = new Response(404); - $has404StatusCode = function ($response) { - return $response->getStatusCode() === 404; - }; + $this->server->setResponse($defaultResponse); - $this->transmitter->transmit( - Argument::any(), - Argument::that($has404StatusCode) - )->shouldHaveBeenCalled(); - } - - public function testRespondsWithUnhandledResponseWhenReachingEndOfStack() - { - $unhandledResponse = (new Response(404)) - ->withBody(new Stream("I can't find it!")); - - $this->server->setUnhandledResponse($unhandledResponse); + $this->server->add( + function ($rqst, $resp, $next) { + return $next($rqst, $resp); + } + ); $this->server->respond(); - $isExpectedResponse = function ($response) use ($unhandledResponse) { - return $response === $unhandledResponse; - }; - $this->transmitter->transmit( Argument::any(), - Argument::that($isExpectedResponse) + $defaultResponse )->shouldHaveBeenCalled(); }