Router can provide middleware called only for matched routes.
This commit is contained in:
parent
29cad3687e
commit
9aab0d780e
|
|
@ -4,6 +4,7 @@ namespace WellRESTed\Routing;
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use WellRESTed\Dispatching\Dispatcher;
|
||||||
use WellRESTed\Dispatching\DispatcherInterface;
|
use WellRESTed\Dispatching\DispatcherInterface;
|
||||||
use WellRESTed\Routing\Route\RouteFactory;
|
use WellRESTed\Routing\Route\RouteFactory;
|
||||||
use WellRESTed\Routing\Route\RouteFactoryInterface;
|
use WellRESTed\Routing\Route\RouteFactoryInterface;
|
||||||
|
|
@ -25,6 +26,8 @@ class Router implements RouterInterface
|
||||||
private $prefixRoutes;
|
private $prefixRoutes;
|
||||||
/** @var RouteInterface[] Hash array mapping path prefixes to routes */
|
/** @var RouteInterface[] Hash array mapping path prefixes to routes */
|
||||||
private $patternRoutes;
|
private $patternRoutes;
|
||||||
|
/** @var mixed[] List array of middleware */
|
||||||
|
protected $stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Router.
|
* Create a new Router.
|
||||||
|
|
@ -37,35 +40,40 @@ class Router implements RouterInterface
|
||||||
* stored with the name. The value will be an array containing all of the
|
* stored with the name. The value will be an array containing all of the
|
||||||
* path variables.
|
* path variables.
|
||||||
*
|
*
|
||||||
* @param DispatcherInterface $dispatcher Instance to use for dispatching
|
* @param DispatcherInterface $dispatcher
|
||||||
* middleware.
|
* Instance to use for dispatching middleware and handlers.
|
||||||
* @param string|null $pathVariablesAttributeName Attribute name for
|
* @param string|null $pathVariablesAttributeName
|
||||||
* matched path variables. A null value sets attributes directly.
|
* Attribute name for matched path variables. A null value sets
|
||||||
|
* attributes directly.
|
||||||
*/
|
*/
|
||||||
public function __construct(DispatcherInterface $dispatcher = null, $pathVariablesAttributeName = null)
|
public function __construct($dispatcher = null, $pathVariablesAttributeName = null)
|
||||||
{
|
{
|
||||||
$this->dispatcher = $dispatcher;
|
$this->dispatcher = $dispatcher ?? $this->getDefaultDispatcher();
|
||||||
$this->pathVariablesAttributeName = $pathVariablesAttributeName;
|
$this->pathVariablesAttributeName = $pathVariablesAttributeName;
|
||||||
$this->factory = $this->getRouteFactory($this->dispatcher);
|
$this->factory = $this->getRouteFactory($this->dispatcher);
|
||||||
$this->routes = [];
|
$this->routes = [];
|
||||||
$this->staticRoutes = [];
|
$this->staticRoutes = [];
|
||||||
$this->prefixRoutes = [];
|
$this->prefixRoutes = [];
|
||||||
$this->patternRoutes = [];
|
$this->patternRoutes = [];
|
||||||
|
$this->stack = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
|
public function __invoke(
|
||||||
{
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
$next
|
||||||
|
) {
|
||||||
// Use only the path for routing.
|
// Use only the path for routing.
|
||||||
$requestTarget = parse_url($request->getRequestTarget(), PHP_URL_PATH);
|
$requestTarget = parse_url($request->getRequestTarget(), PHP_URL_PATH);
|
||||||
|
|
||||||
$route = $this->getStaticRoute($requestTarget);
|
$route = $this->getStaticRoute($requestTarget);
|
||||||
if ($route) {
|
if ($route) {
|
||||||
return $route($request, $response, $next);
|
return $this->dispatch($route, $request, $response, $next);
|
||||||
}
|
}
|
||||||
|
|
||||||
$route = $this->getPrefixRoute($requestTarget);
|
$route = $this->getPrefixRoute($requestTarget);
|
||||||
if ($route) {
|
if ($route) {
|
||||||
return $route($request, $response, $next);
|
return $this->dispatch($route, $request, $response, $next);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try each of the routes.
|
// Try each of the routes.
|
||||||
|
|
@ -79,7 +87,7 @@ class Router implements RouterInterface
|
||||||
$request = $request->withAttribute($name, $value);
|
$request = $request->withAttribute($name, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $route($request, $response, $next);
|
return $this->dispatch($route, $request, $response, $next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,6 +95,21 @@ class Router implements RouterInterface
|
||||||
return $next($request, $response);
|
return $next($request, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function dispatch(
|
||||||
|
$route,
|
||||||
|
ServerRequestInterface $request,
|
||||||
|
ResponseInterface $response,
|
||||||
|
$next
|
||||||
|
) {
|
||||||
|
if (!$this->stack) {
|
||||||
|
return $route($request, $response, $next);
|
||||||
|
}
|
||||||
|
$stack = array_merge($this->stack, [$route]);
|
||||||
|
return $this->dispatcher->dispatch(
|
||||||
|
$stack, $request, $response, $next
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register middleware with the router for a given path and method.
|
* Register middleware with the router for a given path and method.
|
||||||
*
|
*
|
||||||
|
|
@ -122,6 +145,37 @@ class Router implements RouterInterface
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a new middleware onto the stack. Middleware for a router runs only
|
||||||
|
* when the router has a route matching the request.
|
||||||
|
*
|
||||||
|
* $middleware may be:
|
||||||
|
* - An instance implementing MiddlewareInterface
|
||||||
|
* - A string containing the fully qualified class name of a class
|
||||||
|
* implementing MiddlewareInterface
|
||||||
|
* - A callable that returns an instance implementing MiddleInterface
|
||||||
|
* - A callable matching the signature of MiddlewareInterface::dispatch
|
||||||
|
* @see DispatchedInterface::dispatch
|
||||||
|
*
|
||||||
|
* @param mixed $middleware Middleware to dispatch in sequence
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function addMiddleware($middleware)
|
||||||
|
{
|
||||||
|
$this->stack[] = $middleware;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an instance to dispatch middleware.
|
||||||
|
*
|
||||||
|
* @return DispatcherInterface
|
||||||
|
*/
|
||||||
|
protected function getDefaultDispatcher()
|
||||||
|
{
|
||||||
|
return new Dispatcher();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DispatcherInterface
|
* @param DispatcherInterface
|
||||||
* @return RouteFactoryInterface
|
* @return RouteFactoryInterface
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,24 @@ interface RouterInterface extends MiddlewareInterface
|
||||||
* @param string $target Request target or pattern to match
|
* @param string $target Request target or pattern to match
|
||||||
* @param string $method HTTP method(s) to match
|
* @param string $method HTTP method(s) to match
|
||||||
* @param mixed $middleware Middleware to dispatch
|
* @param mixed $middleware Middleware to dispatch
|
||||||
* @return self
|
* @return static
|
||||||
*/
|
*/
|
||||||
public function register($method, $target, $middleware);
|
public function register($method, $target, $middleware);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a new middleware onto the stack. Middleware for a router runs only
|
||||||
|
* when the router has a route matching the request.
|
||||||
|
*
|
||||||
|
* $middleware may be:
|
||||||
|
* - An instance implementing MiddlewareInterface
|
||||||
|
* - A string containing the fully qualified class name of a class
|
||||||
|
* implementing MiddlewareInterface
|
||||||
|
* - A callable that returns an instance implementing MiddleInterface
|
||||||
|
* - A callable matching the signature of MiddlewareInterface::dispatch
|
||||||
|
* @see DispatchedInterface::dispatch
|
||||||
|
*
|
||||||
|
* @param mixed $middleware Middleware to dispatch in sequence
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public function addMiddleware($middleware);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ use Prophecy\Argument;
|
||||||
use WellRESTed\Dispatching\Dispatcher;
|
use WellRESTed\Dispatching\Dispatcher;
|
||||||
use WellRESTed\Message\Response;
|
use WellRESTed\Message\Response;
|
||||||
use WellRESTed\Message\ServerRequest;
|
use WellRESTed\Message\ServerRequest;
|
||||||
|
use WellRESTed\Routing\MethodMapInterface;
|
||||||
|
use WellRESTed\Routing\Route\RouteFactory;
|
||||||
use WellRESTed\Routing\Route\RouteInterface;
|
use WellRESTed\Routing\Route\RouteInterface;
|
||||||
use WellRESTed\Routing\Router;
|
use WellRESTed\Routing\Router;
|
||||||
use WellRESTed\Test\Doubles\NextMock;
|
use WellRESTed\Test\Doubles\NextMock;
|
||||||
|
|
@ -25,31 +27,27 @@ class RouterTest extends TestCase
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->methodMap = $this->prophesize('WellRESTed\Routing\MethodMapInterface');
|
$this->methodMap = $this->prophesize(MethodMapInterface::class);
|
||||||
$this->methodMap->register(Argument::cetera());
|
$this->methodMap->register(Argument::cetera());
|
||||||
|
|
||||||
$this->route = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$this->route = $this->prophesize(RouteInterface::class);
|
||||||
$this->route->__invoke(Argument::cetera())->willReturn();
|
$this->route->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
$this->route->getMethodMap()->willReturn($this->methodMap->reveal());
|
$this->route->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$this->route->getType()->willReturn(RouteInterface::TYPE_STATIC);
|
$this->route->getType()->willReturn(RouteInterface::TYPE_STATIC);
|
||||||
$this->route->getTarget()->willReturn("/");
|
$this->route->getTarget()->willReturn("/");
|
||||||
$this->route->getPathVariables()->willReturn([]);
|
$this->route->getPathVariables()->willReturn([]);
|
||||||
|
|
||||||
$this->factory = $this->prophesize('WellRESTed\Routing\Route\RouteFactory');
|
$this->factory = $this->prophesize(RouteFactory::class);
|
||||||
$this->factory->create(Argument::any())->willReturn($this->route->reveal());
|
$this->factory->create(Argument::any())
|
||||||
|
->willReturn($this->route->reveal());
|
||||||
|
|
||||||
|
RouterWithFactory::$routeFactory = $this->factory->reveal();
|
||||||
|
|
||||||
|
$this->router = new RouterWithFactory();
|
||||||
|
|
||||||
$this->request = new ServerRequest();
|
$this->request = new ServerRequest();
|
||||||
$this->response = new Response();
|
$this->response = new Response();
|
||||||
$this->next = new NextMock();
|
$this->next = new NextMock();
|
||||||
|
|
||||||
$this->router = $this->getMockBuilder('WellRESTed\Routing\Router')
|
|
||||||
->setMethods(["getRouteFactory"])
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
$this->router->expects($this->any())
|
|
||||||
->method("getRouteFactory")
|
|
||||||
->will($this->returnValue($this->factory->reveal()));
|
|
||||||
$this->router->__construct(new Dispatcher());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
@ -57,7 +55,7 @@ class RouterTest extends TestCase
|
||||||
|
|
||||||
public function testCreatesInstance()
|
public function testCreatesInstance()
|
||||||
{
|
{
|
||||||
$router = new Router(new Dispatcher());
|
$router = new Router();
|
||||||
$this->assertNotNull($router);
|
$this->assertNotNull($router);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,6 +65,7 @@ class RouterTest extends TestCase
|
||||||
public function testCreatesRouteForTarget()
|
public function testCreatesRouteForTarget()
|
||||||
{
|
{
|
||||||
$this->router->register("GET", "/", "middleware");
|
$this->router->register("GET", "/", "middleware");
|
||||||
|
|
||||||
$this->factory->create("/")->shouldHaveBeenCalled();
|
$this->factory->create("/")->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,12 +73,14 @@ class RouterTest extends TestCase
|
||||||
{
|
{
|
||||||
$this->router->register("GET", "/", "middleware");
|
$this->router->register("GET", "/", "middleware");
|
||||||
$this->router->register("POST", "/", "middleware");
|
$this->router->register("POST", "/", "middleware");
|
||||||
|
|
||||||
$this->factory->create("/")->shouldHaveBeenCalledTimes(1);
|
$this->factory->create("/")->shouldHaveBeenCalledTimes(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPassesMethodAndMiddlewareToMethodMap()
|
public function testPassesMethodAndMiddlewareToMethodMap()
|
||||||
{
|
{
|
||||||
$this->router->register("GET", "/", "middleware");
|
$this->router->register("GET", "/", "middleware");
|
||||||
|
|
||||||
$this->methodMap->register("GET", "middleware")->shouldHaveBeenCalled();
|
$this->methodMap->register("GET", "middleware")->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +98,8 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", $target, "middleware");
|
$this->router->register("GET", $target, "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$this->route->__invoke($this->request, $this->response, $this->next)->shouldHaveBeenCalled();
|
$this->route->__invoke(Argument::cetera())
|
||||||
|
->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDispatchesPrefixRoute()
|
public function testDispatchesPrefixRoute()
|
||||||
|
|
@ -111,7 +113,8 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", $target, "middleware");
|
$this->router->register("GET", $target, "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$this->route->__invoke($this->request, $this->response, $this->next)->shouldHaveBeenCalled();
|
$this->route->__invoke(Argument::cetera())
|
||||||
|
->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDispatchesPatternRoute()
|
public function testDispatchesPatternRoute()
|
||||||
|
|
@ -126,22 +129,23 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", $target, "middleware");
|
$this->router->register("GET", $target, "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$this->route->__invoke($this->request, $this->response, $this->next)->shouldHaveBeenCalled();
|
$this->route->__invoke(Argument::cetera())
|
||||||
|
->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDispatchesStaticRouteBeforePrefixRoute()
|
public function testDispatchesStaticRouteBeforePrefixRoute()
|
||||||
{
|
{
|
||||||
$staticRoute = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$staticRoute = $this->prophesize(RouteInterface::class);
|
||||||
$staticRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
$staticRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$staticRoute->getTarget()->willReturn("/cats/");
|
$staticRoute->getTarget()->willReturn("/cats/");
|
||||||
$staticRoute->getType()->willReturn(RouteInterface::TYPE_STATIC);
|
$staticRoute->getType()->willReturn(RouteInterface::TYPE_STATIC);
|
||||||
$staticRoute->__invoke(Argument::cetera())->willReturn();
|
$staticRoute->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$prefixRoute = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$prefixRoute = $this->prophesize(RouteInterface::class);
|
||||||
$prefixRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
$prefixRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$prefixRoute->getTarget()->willReturn("/cats/*");
|
$prefixRoute->getTarget()->willReturn("/cats/*");
|
||||||
$prefixRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
$prefixRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
||||||
$prefixRoute->__invoke(Argument::cetera())->willReturn();
|
$prefixRoute->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$this->request = $this->request->withRequestTarget("/cats/");
|
$this->request = $this->request->withRequestTarget("/cats/");
|
||||||
|
|
||||||
|
|
@ -152,26 +156,28 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", "/cats/*", "middleware");
|
$this->router->register("GET", "/cats/*", "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$staticRoute->__invoke($this->request, $this->response, $this->next)->shouldHaveBeenCalled();
|
$staticRoute->__invoke(Argument::cetera())
|
||||||
|
->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDispatchesLongestMatchingPrefixRoute()
|
public function testDispatchesLongestMatchingPrefixRoute()
|
||||||
{
|
{
|
||||||
// Note: The longest route is also good for 2 points in Settlers of Catan.
|
// Note: The longest route is also good for 2 points in Settlers of Catan.
|
||||||
|
|
||||||
$shortRoute = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$shortRoute = $this->prophesize(RouteInterface::class);
|
||||||
$shortRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
$shortRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$shortRoute->getTarget()->willReturn("/animals/*");
|
$shortRoute->getTarget()->willReturn("/animals/*");
|
||||||
$shortRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
$shortRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
||||||
$shortRoute->__invoke(Argument::cetera())->willReturn();
|
$shortRoute->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$longRoute = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$longRoute = $this->prophesize(RouteInterface::class);
|
||||||
$longRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
$longRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$longRoute->getTarget()->willReturn("/animals/cats/*");
|
$longRoute->getTarget()->willReturn("/animals/cats/*");
|
||||||
$longRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
$longRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
||||||
$longRoute->__invoke(Argument::cetera())->willReturn();
|
$longRoute->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$this->request = $this->request->withRequestTarget("/animals/cats/molly");
|
$this->request = $this->request
|
||||||
|
->withRequestTarget("/animals/cats/molly");
|
||||||
|
|
||||||
$this->factory->create("/animals/*")->willReturn($shortRoute->reveal());
|
$this->factory->create("/animals/*")->willReturn($shortRoute->reveal());
|
||||||
$this->factory->create("/animals/cats/*")->willReturn($longRoute->reveal());
|
$this->factory->create("/animals/cats/*")->willReturn($longRoute->reveal());
|
||||||
|
|
@ -180,22 +186,23 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", "/animals/cats/*", "middleware");
|
$this->router->register("GET", "/animals/cats/*", "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$longRoute->__invoke($this->request, $this->response, $this->next)->shouldHaveBeenCalled();
|
$longRoute->__invoke(Argument::cetera())
|
||||||
|
->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDispatchesPrefixRouteBeforePatternRoute()
|
public function testDispatchesPrefixRouteBeforePatternRoute()
|
||||||
{
|
{
|
||||||
$prefixRoute = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$prefixRoute = $this->prophesize(RouteInterface::class);
|
||||||
$prefixRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
$prefixRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$prefixRoute->getTarget()->willReturn("/cats/*");
|
$prefixRoute->getTarget()->willReturn("/cats/*");
|
||||||
$prefixRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
$prefixRoute->getType()->willReturn(RouteInterface::TYPE_PREFIX);
|
||||||
$prefixRoute->__invoke(Argument::cetera())->willReturn();
|
$prefixRoute->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$patternRoute = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$patternRoute = $this->prophesize(RouteInterface::class);
|
||||||
$patternRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
$patternRoute->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$patternRoute->getTarget()->willReturn("/cats/{id}");
|
$patternRoute->getTarget()->willReturn("/cats/{id}");
|
||||||
$patternRoute->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
$patternRoute->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
||||||
$patternRoute->__invoke(Argument::cetera())->willReturn();
|
$patternRoute->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$this->request = $this->request->withRequestTarget("/cats/");
|
$this->request = $this->request->withRequestTarget("/cats/");
|
||||||
|
|
||||||
|
|
@ -206,26 +213,27 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", "/cats/{id}", "middleware");
|
$this->router->register("GET", "/cats/{id}", "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$prefixRoute->__invoke($this->request, $this->response, $this->next)->shouldHaveBeenCalled();
|
$prefixRoute->__invoke(Argument::cetera())
|
||||||
|
->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDispatchesFirstMatchingPatternRoute()
|
public function testDispatchesFirstMatchingPatternRoute()
|
||||||
{
|
{
|
||||||
$patternRoute1 = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$patternRoute1 = $this->prophesize(RouteInterface::class);
|
||||||
$patternRoute1->getMethodMap()->willReturn($this->methodMap->reveal());
|
$patternRoute1->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$patternRoute1->getTarget()->willReturn("/cats/{id}");
|
$patternRoute1->getTarget()->willReturn("/cats/{id}");
|
||||||
$patternRoute1->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
$patternRoute1->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
||||||
$patternRoute1->getPathVariables()->willReturn([]);
|
$patternRoute1->getPathVariables()->willReturn([]);
|
||||||
$patternRoute1->matchesRequestTarget(Argument::any())->willReturn(true);
|
$patternRoute1->matchesRequestTarget(Argument::any())->willReturn(true);
|
||||||
$patternRoute1->__invoke(Argument::cetera())->willReturn();
|
$patternRoute1->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$patternRoute2 = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$patternRoute2 = $this->prophesize(RouteInterface::class);
|
||||||
$patternRoute2->getMethodMap()->willReturn($this->methodMap->reveal());
|
$patternRoute2->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$patternRoute2->getTarget()->willReturn("/cats/{name}");
|
$patternRoute2->getTarget()->willReturn("/cats/{name}");
|
||||||
$patternRoute2->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
$patternRoute2->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
||||||
$patternRoute2->getPathVariables()->willReturn([]);
|
$patternRoute2->getPathVariables()->willReturn([]);
|
||||||
$patternRoute2->matchesRequestTarget(Argument::any())->willReturn(true);
|
$patternRoute2->matchesRequestTarget(Argument::any())->willReturn(true);
|
||||||
$patternRoute2->__invoke(Argument::cetera())->willReturn();
|
$patternRoute2->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$this->request = $this->request->withRequestTarget("/cats/molly");
|
$this->request = $this->request->withRequestTarget("/cats/molly");
|
||||||
|
|
||||||
|
|
@ -236,26 +244,27 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", "/cats/{name}", "middleware");
|
$this->router->register("GET", "/cats/{name}", "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$patternRoute1->__invoke($this->request, $this->response, $this->next)->shouldHaveBeenCalled();
|
$patternRoute1->__invoke(Argument::cetera())
|
||||||
|
->shouldHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStopsTestingPatternsAfterFirstSuccessfulMatch()
|
public function testStopsTestingPatternsAfterFirstSuccessfulMatch()
|
||||||
{
|
{
|
||||||
$patternRoute1 = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$patternRoute1 = $this->prophesize(RouteInterface::class);
|
||||||
$patternRoute1->getMethodMap()->willReturn($this->methodMap->reveal());
|
$patternRoute1->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$patternRoute1->getTarget()->willReturn("/cats/{id}");
|
$patternRoute1->getTarget()->willReturn("/cats/{id}");
|
||||||
$patternRoute1->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
$patternRoute1->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
||||||
$patternRoute1->getPathVariables()->willReturn([]);
|
$patternRoute1->getPathVariables()->willReturn([]);
|
||||||
$patternRoute1->matchesRequestTarget(Argument::any())->willReturn(true);
|
$patternRoute1->matchesRequestTarget(Argument::any())->willReturn(true);
|
||||||
$patternRoute1->__invoke(Argument::cetera())->willReturn();
|
$patternRoute1->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$patternRoute2 = $this->prophesize('WellRESTed\Routing\Route\RouteInterface');
|
$patternRoute2 = $this->prophesize(RouteInterface::class);
|
||||||
$patternRoute2->getMethodMap()->willReturn($this->methodMap->reveal());
|
$patternRoute2->getMethodMap()->willReturn($this->methodMap->reveal());
|
||||||
$patternRoute2->getTarget()->willReturn("/cats/{name}");
|
$patternRoute2->getTarget()->willReturn("/cats/{name}");
|
||||||
$patternRoute2->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
$patternRoute2->getType()->willReturn(RouteInterface::TYPE_PATTERN);
|
||||||
$patternRoute2->getPathVariables()->willReturn([]);
|
$patternRoute2->getPathVariables()->willReturn([]);
|
||||||
$patternRoute2->matchesRequestTarget(Argument::any())->willReturn(true);
|
$patternRoute2->matchesRequestTarget(Argument::any())->willReturn(true);
|
||||||
$patternRoute2->__invoke(Argument::cetera())->willReturn();
|
$patternRoute2->__invoke(Argument::cetera())->willReturn(new Response());
|
||||||
|
|
||||||
$this->request = $this->request->withRequestTarget("/cats/molly");
|
$this->request = $this->request->withRequestTarget("/cats/molly");
|
||||||
|
|
||||||
|
|
@ -266,7 +275,8 @@ class RouterTest extends TestCase
|
||||||
$this->router->register("GET", "/cats/{name}", "middleware");
|
$this->router->register("GET", "/cats/{name}", "middleware");
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
$patternRoute2->matchesRequestTarget(Argument::any())->shouldNotHaveBeenCalled();
|
$patternRoute2->matchesRequestTarget(Argument::any())
|
||||||
|
->shouldNotHaveBeenCalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMatchesPathAgainstRouteWithoutQuery()
|
public function testMatchesPathAgainstRouteWithoutQuery()
|
||||||
|
|
@ -362,4 +372,67 @@ class RouterTest extends TestCase
|
||||||
$this->router->__invoke($this->request, $this->response, $this->next);
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
$this->assertTrue($this->next->called);
|
$this->assertTrue($this->next->called);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Middleware for Routes
|
||||||
|
|
||||||
|
public function testCallsRouterMiddlewareBeforeRouteMiddleware()
|
||||||
|
{
|
||||||
|
$middlewareRequest = new ServerRequest();
|
||||||
|
$middlewareResponse = new Response();
|
||||||
|
|
||||||
|
$middleware = function ($rqst, $resp, $next) use (
|
||||||
|
$middlewareRequest,
|
||||||
|
$middlewareResponse
|
||||||
|
) {
|
||||||
|
return $next($middlewareRequest, $middlewareResponse);
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->router->addMiddleware($middleware);
|
||||||
|
$this->router->register("GET", "/", "Handler");
|
||||||
|
|
||||||
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
|
$this->route->__invoke(
|
||||||
|
$middlewareRequest,
|
||||||
|
$middlewareResponse,
|
||||||
|
Argument::any())->shouldHaveBeenCalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDoesNotCallRouterMiddlewareWhenNoRouteMatches()
|
||||||
|
{
|
||||||
|
$middlewareCalled = false;
|
||||||
|
$middlewareRequest = new ServerRequest();
|
||||||
|
$middlewareResponse = new Response();
|
||||||
|
|
||||||
|
$middleware = function ($rqst, $resp, $next) use (
|
||||||
|
$middlewareRequest,
|
||||||
|
$middlewareResponse,
|
||||||
|
&$middlewareCalled
|
||||||
|
) {
|
||||||
|
$middlewareCalled = true;
|
||||||
|
return $next($middlewareRequest, $middlewareResponse);
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->request = $this->request->withRequestTarget("/no/match");
|
||||||
|
|
||||||
|
$this->router->addMiddleware($middleware);
|
||||||
|
$this->router->register("GET", "/", "Handler");
|
||||||
|
|
||||||
|
$this->router->__invoke($this->request, $this->response, $this->next);
|
||||||
|
|
||||||
|
$this->assertFalse($middlewareCalled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class RouterWithFactory extends Router
|
||||||
|
{
|
||||||
|
static $routeFactory;
|
||||||
|
|
||||||
|
protected function getRouteFactory($dispatcher)
|
||||||
|
{
|
||||||
|
return self::$routeFactory;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue