Add Router
This commit is contained in:
parent
57271fa19f
commit
decf712354
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace WellRESTed\Routing;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use WellRESTed\HttpExceptions\HttpException;
|
||||
use WellRESTed\Routing\Route\RouteFactory;
|
||||
use WellRESTed\Stream\StringStream;
|
||||
|
||||
class Router implements MiddlewareInterface
|
||||
{
|
||||
/** @var array Hash array of status code => error handler */
|
||||
private $statusHandlers;
|
||||
/** @var RouteTable Collection of routes */
|
||||
private $routeTable;
|
||||
/** @var RouteFactory */
|
||||
private $routeFactory;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->routeTable = new RouteTable();
|
||||
$this->routeFactory = new RouteFactory($this->routeTable);
|
||||
$this->statusHandlers = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a route given a string path, a handler, and optional
|
||||
* extra arguments.
|
||||
*
|
||||
* The method will determine the most appropriate route subclass to use
|
||||
* and will forward the arguments on to the subclass's constructor.
|
||||
*
|
||||
* - Paths with no special characters will generate StaticRoutes
|
||||
* - Paths ending with * will generate PrefixRoutes
|
||||
* - Paths containing URI variables (e.g., {id}) will generate TemplateRoutes
|
||||
* - Regular exressions will generate RegexRoutes
|
||||
*
|
||||
* @param string $target Path, prefix, or pattern to match
|
||||
* @param mixed $middleware Middleware to dispatch
|
||||
* @param $defaultPattern @see TemplateRoute
|
||||
* @param $variablePatterns @see TemplateRoute
|
||||
*/
|
||||
public function add($target, $middleware, $defaultPattern = null, $variablePatterns = null)
|
||||
{
|
||||
$this->routeFactory->registerRoute($target, $middleware, $defaultPattern, $variablePatterns);
|
||||
}
|
||||
|
||||
public function setStatusHandler($statusCode, $middleware)
|
||||
{
|
||||
$this->statusHandlers[$statusCode] = $middleware;
|
||||
}
|
||||
|
||||
public function dispatch(ServerRequestInterface $request, ResponseInterface &$response)
|
||||
{
|
||||
try {
|
||||
$this->routeTable->dispatch($request, $response);
|
||||
} catch (HttpException $e) {
|
||||
$response = $response->withStatus($e->getCode());
|
||||
$response = $response->withBody(new StringStream($e->getMessage()));
|
||||
}
|
||||
$statusCode = $response->getStatusCode();
|
||||
if (isset($this->statusHandlers[$statusCode])) {
|
||||
$middleware = $this->statusHandlers[$statusCode];
|
||||
$dispatcher = new Dispatcher();
|
||||
$dispatcher->dispatch($middleware, $request, $response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace WellRESTed\Test\Unit\Routing;
|
||||
|
||||
use Prophecy\Argument;
|
||||
use WellRESTed\HttpExceptions\NotFoundException;
|
||||
use WellRESTed\Routing\Router;
|
||||
|
||||
/**
|
||||
* @covers WellRESTed\Routing\Router
|
||||
* @uses WellRESTed\Routing\Dispatcher
|
||||
* @uses WellRESTed\Routing\RouteTable
|
||||
* @uses WellRESTed\Routing\Route\RouteFactory
|
||||
* @uses WellRESTed\Routing\Route\RegexRoute
|
||||
* @uses WellRESTed\Routing\Route\TemplateRoute
|
||||
* @uses WellRESTed\Routing\Route\PrefixRoute
|
||||
* @uses WellRESTed\Routing\Route\StaticRoute
|
||||
* @uses WellRESTed\Routing\Route\Route
|
||||
* @uses WellRESTed\Stream\Stream
|
||||
* @uses WellRESTed\Stream\StringStream
|
||||
*/
|
||||
class RouterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $request;
|
||||
private $response;
|
||||
private $middleware;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->request = $this->prophesize("\\Psr\\Http\\Message\\ServerRequestInterface");
|
||||
$this->response = $this->prophesize("\\Psr\\Http\\Message\\ResponseInterface");
|
||||
$this->response->withStatus(Argument::any())->willReturn($this->response->reveal());
|
||||
$this->response->withBody(Argument::any())->willReturn($this->response->reveal());
|
||||
$this->response->getStatusCode()->willReturn(200);
|
||||
$this->middleware = $this->prophesize("\\WellRESTed\\Routing\\MiddlewareInterface");
|
||||
$this->middleware->dispatch(Argument::cetera())->willReturn();
|
||||
}
|
||||
|
||||
public function testDispatchedRoute()
|
||||
{
|
||||
$this->request->getRequestTarget()->willReturn("/cats/");
|
||||
|
||||
$router = new Router();
|
||||
$router->add("/cats/", $this->middleware->reveal());
|
||||
$router->dispatch($this->request->reveal(), $this->response->reveal());
|
||||
|
||||
$this->middleware->dispatch(Argument::cetera())->shouldHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function testRespondsWithErrorResponseForHttpException()
|
||||
{
|
||||
$this->request->getRequestTarget()->willReturn("/cats/");
|
||||
$this->middleware->dispatch(Argument::cetera())->willThrow(new NotFoundException());
|
||||
|
||||
$router = new Router();
|
||||
$router->add("/cats/", $this->middleware->reveal());
|
||||
$router->dispatch($this->request->reveal(), $this->response->reveal());
|
||||
|
||||
$this->response->withStatus(404)->shouldHaveBeenCalled();
|
||||
}
|
||||
|
||||
public function testDispatchesErrorHandlerForStatusCode()
|
||||
{
|
||||
$this->response->getStatusCode()->willReturn(403);
|
||||
|
||||
$statusMiddleware = $this->prophesize("\\WellRESTed\\Routing\\MiddlewareInterface");
|
||||
$statusMiddleware->dispatch(Argument::cetera())->willReturn();
|
||||
|
||||
$router = new Router();
|
||||
$router->add("/cats/", $this->middleware->reveal());
|
||||
$router->setStatusHandler(403, $statusMiddleware->reveal());
|
||||
$router->dispatch($this->request->reveal(), $this->response->reveal());
|
||||
|
||||
$statusMiddleware->dispatch(Argument::cetera())->shouldHaveBeenCalled();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue