Skip to content

Commit

Permalink
Fix to allow multiple routes with the same path across differing cond…
Browse files Browse the repository at this point in the history
…itions. Fixes #298
  • Loading branch information
philipobenito committed Jul 21, 2021
1 parent 8bdbf0a commit b66c107
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 34 deletions.
25 changes: 2 additions & 23 deletions src/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
class Dispatcher extends GroupCountBasedDispatcher implements
MiddlewareAwareInterface,
RequestHandlerInterface,
RouteConditionHandlerInterface,
StrategyAwareInterface
{
use MiddlewareAwareTrait;
use RouteConditionHandlerTrait;
use StrategyAwareTrait;

public function dispatchRequest(ServerRequestInterface $request): ResponseInterface
Expand Down Expand Up @@ -66,29 +68,6 @@ protected function ensureHandlerIsRoute($matchingHandler, $httpMethod, $uri): Ro
return new Route($httpMethod, $uri, $matchingHandler);
}

protected function isExtraConditionMatch(Route $route, ServerRequestInterface $request): bool
{
// check for scheme condition
$scheme = $route->getScheme();
if ($scheme !== null && $scheme !== $request->getUri()->getScheme()) {
return false;
}

// check for domain condition
$host = $route->getHost();
if ($host !== null && $host !== $request->getUri()->getHost()) {
return false;
}

// check for port condition
$port = $route->getPort();
if ($port !== null && $port !== $request->getUri()->getPort()) {
return false;
}

return true;
}

protected function requestWithRouteAttributes(ServerRequestInterface $request, Route $route): ServerRequestInterface
{
$routerParams = $route->getVars();
Expand Down
20 changes: 20 additions & 0 deletions src/RouteConditionHandlerTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace League\Route;

use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;

trait RouteConditionHandlerTrait
Expand Down Expand Up @@ -84,4 +85,23 @@ private function checkAndReturnSelf(): RouteConditionHandlerInterface
RouteConditionHandlerInterface::class
));
}

protected function isExtraConditionMatch(Route $route, ServerRequestInterface $request): bool
{
// check for scheme condition
$scheme = $route->getScheme();
if ($scheme !== null && $scheme !== $request->getUri()->getScheme()) {
return false;
}

// check for domain condition
$host = $route->getHost();
if ($host !== null && $host !== $request->getUri()->getHost()) {
return false;
}

// check for port condition
$port = $route->getPort();
return !($port !== null && $port !== $request->getUri()->getPort());
}
}
9 changes: 8 additions & 1 deletion src/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ class Router implements
MiddlewareAwareInterface,
RouteCollectionInterface,
StrategyAwareInterface,
RequestHandlerInterface
RequestHandlerInterface,
RouteConditionHandlerInterface
{
use MiddlewareAwareTrait;
use RouteCollectionTrait;
use RouteConditionHandlerTrait;
use StrategyAwareTrait;

protected const IDENTIFIER_SEPARATOR = "\t";
Expand Down Expand Up @@ -153,6 +155,11 @@ public function prepareRoutes(ServerRequestInterface $request): void

/** @var Route $route */
foreach ($routes as $route) {
// this allows for the same route to be mapped across different routes/hosts etc
if (false === $this->isExtraConditionMatch($route, $request)) {
continue;
}

if ($route->getStrategy() === null) {
$route->setStrategy($this->getStrategy());
}
Expand Down
45 changes: 35 additions & 10 deletions tests/DispatchIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -917,15 +917,39 @@ public function process(

public function testCanMapSameRoutePathOnDifferentConditions(): void
{
$router = new Router();
$routerOne = new Router();
$routerTwo = new Router();

$responseOne = $this->getMockBuilder(ResponseInterface::class)->getMock();
$responseTwo = $this->getMockBuilder(ResponseInterface::class)->getMock();
$responseOne->expects(self::once())->method('withHeader')->willReturnSelf();
$responseTwo->expects(self::once())->method('withHeader')->willReturnSelf();

$routerOne
->get('/', static function (ServerRequestInterface $request) use ($responseOne): ResponseInterface {
return $responseOne->withHeader('test', 'test');
})
->setHost('test1.com')
;

$router
->map('GET', '/', [Controller::class, 'action'])
$routerOne
->get('/', static function (ServerRequestInterface $request) use ($responseOne): ResponseInterface {
return $responseOne->withHeader('test', 'test');
})
->setHost('test2.com')
;

$routerTwo
->get('/', static function (ServerRequestInterface $request) use ($responseTwo): ResponseInterface {
return $responseTwo->withHeader('test', 'test');
})
->setHost('test1.com')
;

$router
->map('GET', '/', [Controller::class, 'action'])
$routerTwo
->get('/', static function (ServerRequestInterface $request) use ($responseTwo): ResponseInterface {
return $responseTwo->withHeader('test', 'test');
})
->setHost('test2.com')
;

Expand All @@ -937,14 +961,15 @@ public function testCanMapSameRoutePathOnDifferentConditions(): void

$uriOne->method('getHost')->willReturn('test1.com');
$uriTwo->method('getHost')->willReturn('test2.com');
$uriOne->method('getPath')->willReturn('/');
$uriTwo->method('getPath')->willReturn('/');

$requestOne->method('getUri')->willReturn($uriOne);
$requestTwo->method('getUri')->willReturn($uriTwo);
$requestOne->method('getMethod')->willReturn('GET');
$requestTwo->method('getMethod')->willReturn('GET');

$responseOne = $router->dispatch($requestOne);
self::assertSame($responseOne->getHeader('action'), 'true');

$responseTwo = $router->dispatch($requestTwo);
self::assertSame($responseTwo->getHeader('action'), 'true');
$routerOne->dispatch($requestOne);
$routerTwo->dispatch($requestTwo);
}
}

0 comments on commit b66c107

Please sign in to comment.