[Routing] support scheme requirement without redirectable dumped matcher
This commit is contained in:
parent
308e12cb59
commit
f9b54c5ccd
@ -29,7 +29,6 @@ class PhpMatcherDumper extends MatcherDumper
|
||||
{
|
||||
private $expressionLanguage;
|
||||
private $signalingException;
|
||||
private $supportsRedirections;
|
||||
|
||||
/**
|
||||
* @var ExpressionFunctionProviderInterface[]
|
||||
@ -57,7 +56,7 @@ class PhpMatcherDumper extends MatcherDumper
|
||||
|
||||
// trailing slash support is only enabled if we know how to redirect the user
|
||||
$interfaces = class_implements($options['base_class']);
|
||||
$this->supportsRedirections = isset($interfaces[RedirectableUrlMatcherInterface::class]);
|
||||
$supportsRedirections = isset($interfaces[RedirectableUrlMatcherInterface::class]);
|
||||
|
||||
return <<<EOF
|
||||
<?php
|
||||
@ -77,7 +76,7 @@ class {$options['class']} extends {$options['base_class']}
|
||||
\$this->context = \$context;
|
||||
}
|
||||
|
||||
{$this->generateMatchMethod()}
|
||||
{$this->generateMatchMethod($supportsRedirections)}
|
||||
}
|
||||
|
||||
EOF;
|
||||
@ -91,7 +90,7 @@ EOF;
|
||||
/**
|
||||
* Generates the code for the match method implementing UrlMatcherInterface.
|
||||
*/
|
||||
private function generateMatchMethod(): string
|
||||
private function generateMatchMethod(bool $supportsRedirections): string
|
||||
{
|
||||
// Group hosts by same-suffix, re-order when possible
|
||||
$matchHost = false;
|
||||
@ -111,7 +110,7 @@ EOF;
|
||||
|
||||
$code = <<<EOF
|
||||
{
|
||||
\$allow = array();
|
||||
\$allow = \$allowSchemes = array();
|
||||
\$pathinfo = rawurldecode(\$rawPathinfo);
|
||||
\$context = \$this->context;
|
||||
\$requestMethod = \$canonicalMethod = \$context->getMethod();
|
||||
@ -124,25 +123,44 @@ $code
|
||||
|
||||
EOF;
|
||||
|
||||
if ($this->supportsRedirections) {
|
||||
if ($supportsRedirections) {
|
||||
return <<<'EOF'
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow)) {
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
|
||||
EOF
|
||||
.$code."\n return null;\n }";
|
||||
@ -238,9 +256,6 @@ EOF
|
||||
}
|
||||
|
||||
if (!$route->getCondition()) {
|
||||
if (!$this->supportsRedirections && $route->getSchemes()) {
|
||||
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
|
||||
}
|
||||
$default .= sprintf(
|
||||
"%s => array(%s, %s, %s, %s),\n",
|
||||
self::export($url),
|
||||
@ -535,8 +550,8 @@ EOF;
|
||||
} else {
|
||||
$code = '';
|
||||
}
|
||||
if ($this->supportsRedirections) {
|
||||
$code .= <<<EOF
|
||||
|
||||
$code .= <<<EOF
|
||||
|
||||
\$hasRequiredScheme = !\$requiredSchemes || isset(\$requiredSchemes[\$context->getScheme()]);
|
||||
if (\$requiredMethods && !isset(\$requiredMethods[\$canonicalMethod]) && !isset(\$requiredMethods[\$requestMethod])) {
|
||||
@ -546,28 +561,13 @@ EOF;
|
||||
break;
|
||||
}
|
||||
if (!\$hasRequiredScheme) {
|
||||
if ('GET' !== \$canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return \$this->redirect(\$rawPathinfo, \$ret['_route'], key(\$requiredSchemes)) + \$ret;
|
||||
}
|
||||
|
||||
return \$ret;
|
||||
|
||||
EOF;
|
||||
} else {
|
||||
$code .= <<<EOF
|
||||
|
||||
if (\$requiredMethods && !isset(\$requiredMethods[\$canonicalMethod]) && !isset(\$requiredMethods[\$requestMethod])) {
|
||||
\$allow += \$requiredMethods;
|
||||
\$allowSchemes += \$requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return \$ret;
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
@ -647,9 +647,6 @@ EOF;
|
||||
}
|
||||
|
||||
if ($schemes = $route->getSchemes()) {
|
||||
if (!$this->supportsRedirections) {
|
||||
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
|
||||
}
|
||||
$schemes = self::export(array_flip($schemes));
|
||||
if ($methods) {
|
||||
$code .= <<<EOF
|
||||
@ -662,11 +659,8 @@ EOF;
|
||||
goto $gotoname;
|
||||
}
|
||||
if (!\$hasRequiredScheme) {
|
||||
if ('GET' !== \$canonicalMethod) {
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)) + \$ret;
|
||||
\$allowSchemes += \$requiredSchemes;
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
|
||||
@ -675,11 +669,8 @@ EOF;
|
||||
$code .= <<<EOF
|
||||
\$requiredSchemes = $schemes;
|
||||
if (!isset(\$requiredSchemes[\$context->getScheme()])) {
|
||||
if ('GET' !== \$canonicalMethod) {
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)) + \$ret;
|
||||
\$allowSchemes += \$requiredSchemes;
|
||||
goto $gotoname;
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Routing\Matcher;
|
||||
|
||||
use Symfony\Component\Routing\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@ -27,38 +27,38 @@ abstract class RedirectableUrlMatcher extends UrlMatcher implements Redirectable
|
||||
try {
|
||||
return parent::match($pathinfo);
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
if ('/' === $pathinfo || !\in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
if (!\in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
try {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
$ret = parent::match($pathinfo);
|
||||
if ($this->allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(current($this->allowSchemes));
|
||||
try {
|
||||
$ret = parent::match($pathinfo);
|
||||
|
||||
return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret;
|
||||
} catch (ResourceNotFoundException $e2) {
|
||||
return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret;
|
||||
} catch (ExceptionInterface $e2) {
|
||||
throw $e;
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' === $pathinfo) {
|
||||
throw $e;
|
||||
} else {
|
||||
try {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
$ret = parent::match($pathinfo);
|
||||
|
||||
return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret;
|
||||
} catch (ExceptionInterface $e2) {
|
||||
if ($this->allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function handleRouteRequirements($pathinfo, $name, Route $route)
|
||||
{
|
||||
// expression condition
|
||||
if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) {
|
||||
return array(self::REQUIREMENT_MISMATCH, null);
|
||||
}
|
||||
|
||||
// check HTTP scheme requirement
|
||||
$scheme = $this->context->getScheme();
|
||||
$schemes = $route->getSchemes();
|
||||
if ($schemes && !$route->hasScheme($scheme)) {
|
||||
return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, current($schemes)));
|
||||
}
|
||||
|
||||
return array(self::REQUIREMENT_MATCH, null);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,19 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
const ROUTE_MATCH = 2;
|
||||
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* Collects HTTP methods that would be allowed for the request.
|
||||
*/
|
||||
protected $allow = array();
|
||||
|
||||
/**
|
||||
* Collects URI schemes that would be allowed for the request.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected $allowSchemes = array();
|
||||
|
||||
protected $routes;
|
||||
protected $request;
|
||||
protected $expressionLanguage;
|
||||
@ -70,7 +82,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
*/
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$this->allow = array();
|
||||
$this->allow = $this->allowSchemes = array();
|
||||
|
||||
if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
|
||||
return $ret;
|
||||
@ -141,7 +153,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
// check HTTP method requirement
|
||||
$hasRequiredScheme = !$route->getSchemes() || $route->hasScheme($this->context->getScheme());
|
||||
if ($requiredMethods = $route->getMethods()) {
|
||||
// HEAD and GET are equivalent as per RFC
|
||||
if ('HEAD' === $method = $this->context->getMethod()) {
|
||||
@ -149,7 +161,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
}
|
||||
|
||||
if (!in_array($method, $requiredMethods)) {
|
||||
if (self::REQUIREMENT_MATCH === $status[0]) {
|
||||
if ($hasRequiredScheme) {
|
||||
$this->allow = array_merge($this->allow, $requiredMethods);
|
||||
}
|
||||
|
||||
@ -157,6 +169,12 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasRequiredScheme) {
|
||||
$this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : array()));
|
||||
}
|
||||
}
|
||||
@ -197,11 +215,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
||||
return array(self::REQUIREMENT_MISMATCH, null);
|
||||
}
|
||||
|
||||
// check HTTP scheme requirement
|
||||
$scheme = $this->context->getScheme();
|
||||
$status = $route->getSchemes() && !$route->hasScheme($scheme) ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
|
||||
|
||||
return array($status, null);
|
||||
return array(self::REQUIREMENT_MATCH, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -64,8 +64,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -209,8 +216,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -2799,8 +2799,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -17,23 +17,42 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow)) {
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -113,11 +132,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -69,8 +69,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
@ -17,23 +17,42 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow)) {
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -90,11 +109,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@ -245,11 +261,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -43,8 +43,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -74,8 +81,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -60,8 +60,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -17,23 +17,42 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow)) {
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -72,11 +91,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@ -115,11 +131,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -44,8 +44,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
list($ret, $requiredHost, $requiredMethods, $requiredSchemes) = $routes[$pathinfo];
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -93,8 +100,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -17,23 +17,42 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
|
||||
public function match($pathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow)) {
|
||||
$allow = $allowSchemes = array();
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $ret;
|
||||
}
|
||||
if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
if ($allow) {
|
||||
throw new MethodNotAllowedException(array_keys($allow));
|
||||
}
|
||||
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
|
||||
// no-op
|
||||
} elseif ($allowSchemes) {
|
||||
redirect_scheme:
|
||||
$scheme = $this->context->getScheme();
|
||||
$this->context->setScheme(key($allowSchemes));
|
||||
try {
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret;
|
||||
}
|
||||
} finally {
|
||||
$this->context->setScheme($scheme);
|
||||
}
|
||||
} elseif ('/' !== $pathinfo) {
|
||||
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
|
||||
if ($ret = $this->doMatch($pathinfo)) {
|
||||
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
|
||||
return $this->redirect($pathinfo, $ret['_route']) + $ret;
|
||||
}
|
||||
if ($allowSchemes) {
|
||||
goto redirect_scheme;
|
||||
}
|
||||
}
|
||||
|
||||
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
|
||||
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -68,11 +87,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@ -127,11 +143,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
if ('GET' !== $canonicalMethod) {
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
@ -57,8 +57,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
}
|
||||
}
|
||||
|
||||
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
|
||||
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
|
||||
$allow += $requiredMethods;
|
||||
if ($hasRequiredScheme) {
|
||||
$allow += $requiredMethods;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!$hasRequiredScheme) {
|
||||
$allowSchemes += $requiredSchemes;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
|
||||
public function match($rawPathinfo)
|
||||
{
|
||||
$allow = array();
|
||||
$allow = $allowSchemes = array();
|
||||
$pathinfo = rawurldecode($rawPathinfo);
|
||||
$context = $this->context;
|
||||
$requestMethod = $canonicalMethod = $context->getMethod();
|
||||
|
@ -17,24 +17,6 @@ use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
class DumpedUrlMatcherTest extends UrlMatcherTest
|
||||
{
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.
|
||||
*/
|
||||
public function testSchemeRequirement()
|
||||
{
|
||||
parent::testSchemeRequirement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.
|
||||
*/
|
||||
public function testSchemeAndMethodMismatch()
|
||||
{
|
||||
parent::testSchemeRequirement();
|
||||
}
|
||||
|
||||
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
||||
{
|
||||
static $i = 0;
|
||||
|
@ -46,24 +46,6 @@ class PhpMatcherDumperTest extends TestCase
|
||||
@unlink($this->dumpPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
*/
|
||||
public function testDumpWhenSchemeIsUsedWithoutAProperDumper()
|
||||
{
|
||||
$collection = new RouteCollection();
|
||||
$collection->add('secure', new Route(
|
||||
'/secure',
|
||||
array(),
|
||||
array(),
|
||||
array(),
|
||||
'',
|
||||
array('https')
|
||||
));
|
||||
$dumper = new PhpMatcherDumper($collection);
|
||||
$dumper->dump();
|
||||
}
|
||||
|
||||
public function testRedirectPreservesUrlEncoding()
|
||||
{
|
||||
$collection = new RouteCollection();
|
||||
|
@ -17,7 +17,7 @@ use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
class RedirectableUrlMatcherTest extends UrlMatcherTest
|
||||
{
|
||||
public function testRedirectWhenNoSlash()
|
||||
public function testMissingTrailingSlash()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/foo/'));
|
||||
@ -27,7 +27,7 @@ class RedirectableUrlMatcherTest extends UrlMatcherTest
|
||||
$matcher->match('/foo');
|
||||
}
|
||||
|
||||
public function testRedirectWhenSlash()
|
||||
public function testExtraTrailingSlash()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/foo'));
|
||||
@ -127,6 +127,16 @@ class RedirectableUrlMatcherTest extends UrlMatcherTest
|
||||
$this->assertSame(array('_route' => 'foo'), $matcher->match('/foo'));
|
||||
}
|
||||
|
||||
public function testMissingTrailingSlashAndScheme()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', (new Route('/foo/'))->setSchemes(array('https')));
|
||||
|
||||
$matcher = $this->getUrlMatcher($coll);
|
||||
$matcher->expects($this->once())->method('redirect')->with('/foo/', 'foo', 'https')->will($this->returnValue(array()));
|
||||
$matcher->match('/foo');
|
||||
}
|
||||
|
||||
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
||||
{
|
||||
return $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($routes, $context ?: new RequestContext()));
|
||||
|
@ -325,6 +325,58 @@ class UrlMatcherTest extends TestCase
|
||||
$matcher->match('/do.t.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
public function testMissingTrailingSlash()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/foo/'));
|
||||
|
||||
$matcher = $this->getUrlMatcher($coll);
|
||||
$matcher->match('/foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
public function testExtraTrailingSlash()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/foo'));
|
||||
|
||||
$matcher = $this->getUrlMatcher($coll);
|
||||
$matcher->match('/foo/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
public function testMissingTrailingSlashForNonSafeMethod()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/foo/'));
|
||||
|
||||
$context = new RequestContext();
|
||||
$context->setMethod('POST');
|
||||
$matcher = $this->getUrlMatcher($coll, $context);
|
||||
$matcher->match('/foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
public function testExtraTrailingSlashForNonSafeMethod()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/foo'));
|
||||
|
||||
$context = new RequestContext();
|
||||
$context->setMethod('POST');
|
||||
$matcher = $this->getUrlMatcher($coll, $context);
|
||||
$matcher->match('/foo/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
@ -336,6 +388,29 @@ class UrlMatcherTest extends TestCase
|
||||
$matcher->match('/foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
public function testSchemeRequirementForNonSafeMethod()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo', new Route('/foo', array(), array(), array(), '', array('https')));
|
||||
|
||||
$context = new RequestContext();
|
||||
$context->setMethod('POST');
|
||||
$matcher = $this->getUrlMatcher($coll, $context);
|
||||
$matcher->match('/foo');
|
||||
}
|
||||
|
||||
public function testSamePathWithDifferentScheme()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('https_route', new Route('/', array(), array(), array(), '', array('https')));
|
||||
$coll->add('http_route', new Route('/', array(), array(), array(), '', array('http')));
|
||||
$matcher = $this->getUrlMatcher($coll);
|
||||
$this->assertEquals(array('_route' => 'http_route'), $matcher->match('/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
|
||||
*/
|
||||
|
Reference in New Issue
Block a user