Add Router

This commit is contained in:
PJ Dietz 2015-04-03 06:35:47 -04:00
parent 57271fa19f
commit decf712354
2 changed files with 145 additions and 0 deletions

69
src/Routing/Router.php Normal file
View File

@ -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);
}
}
}

View File

@ -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();
}
}