[Routing] Throw 405 instead of 404 when redirect is not possible
This commit is contained in:
parent
f7d9701cdf
commit
92842814f6
@ -217,7 +217,7 @@ EOF;
|
|||||||
$methods[] = 'HEAD';
|
$methods[] = 'HEAD';
|
||||||
}
|
}
|
||||||
|
|
||||||
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
|
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('GET', $methods));
|
||||||
|
|
||||||
if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', $compiledRoute->getRegex(), $m)) {
|
if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', $compiledRoute->getRegex(), $m)) {
|
||||||
if ($supportsTrailingSlash && '/' === substr($m['url'], -1)) {
|
if ($supportsTrailingSlash && '/' === substr($m['url'], -1)) {
|
||||||
@ -258,6 +258,42 @@ EOF;
|
|||||||
EOF;
|
EOF;
|
||||||
|
|
||||||
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
|
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
|
||||||
|
|
||||||
|
if ($hasTrailingSlash) {
|
||||||
|
$code .= <<<EOF
|
||||||
|
if ('/' === substr(\$pathinfo, -1)) {
|
||||||
|
// no-op
|
||||||
|
} elseif (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||||
|
\$allow[] = 'GET';
|
||||||
|
goto $gotoname;
|
||||||
|
} else {
|
||||||
|
return \$this->redirect(\$rawPathinfo.'/', '$name');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($schemes = $route->getSchemes()) {
|
||||||
|
if (!$supportsRedirections) {
|
||||||
|
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
|
||||||
|
}
|
||||||
|
$schemes = str_replace("\n", '', var_export(array_flip($schemes), true));
|
||||||
|
$code .= <<<EOF
|
||||||
|
\$requiredSchemes = $schemes;
|
||||||
|
if (!isset(\$requiredSchemes[\$this->context->getScheme()])) {
|
||||||
|
if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||||
|
\$allow[] = 'GET';
|
||||||
|
goto $gotoname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EOF;
|
||||||
|
}
|
||||||
|
|
||||||
if ($methods) {
|
if ($methods) {
|
||||||
if (1 === count($methods)) {
|
if (1 === count($methods)) {
|
||||||
$code .= <<<EOF
|
$code .= <<<EOF
|
||||||
@ -281,35 +317,6 @@ EOF;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hasTrailingSlash) {
|
|
||||||
$code .= <<<EOF
|
|
||||||
if ('/' === substr(\$pathinfo, -1)) {
|
|
||||||
// no-op
|
|
||||||
} elseif (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
|
|
||||||
goto $gotoname;
|
|
||||||
} else {
|
|
||||||
return \$this->redirect(\$rawPathinfo.'/', '$name');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($schemes = $route->getSchemes()) {
|
|
||||||
if (!$supportsRedirections) {
|
|
||||||
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
|
|
||||||
}
|
|
||||||
$schemes = str_replace("\n", '', var_export(array_flip($schemes), true));
|
|
||||||
$code .= <<<EOF
|
|
||||||
\$requiredSchemes = $schemes;
|
|
||||||
if (!isset(\$requiredSchemes[\$this->context->getScheme()])) {
|
|
||||||
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// optimize parameters array
|
// optimize parameters array
|
||||||
if ($matches || $hostMatches) {
|
if ($matches || $hostMatches) {
|
||||||
$vars = array();
|
$vars = array();
|
||||||
@ -333,7 +340,7 @@ EOF;
|
|||||||
}
|
}
|
||||||
$code .= " }\n";
|
$code .= " }\n";
|
||||||
|
|
||||||
if ($methods || $hasTrailingSlash) {
|
if ($hasTrailingSlash || $schemes || $methods) {
|
||||||
$code .= " $gotoname:\n";
|
$code .= " $gotoname:\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
|||||||
if ('/' === substr($pathinfo, -1)) {
|
if ('/' === substr($pathinfo, -1)) {
|
||||||
// no-op
|
// no-op
|
||||||
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||||
|
$allow[] = 'GET';
|
||||||
goto not_baz3;
|
goto not_baz3;
|
||||||
} else {
|
} else {
|
||||||
return $this->redirect($rawPathinfo.'/', 'baz3');
|
return $this->redirect($rawPathinfo.'/', 'baz3');
|
||||||
@ -85,6 +86,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
|||||||
if ('/' === substr($pathinfo, -1)) {
|
if ('/' === substr($pathinfo, -1)) {
|
||||||
// no-op
|
// no-op
|
||||||
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||||
|
$allow[] = 'GET';
|
||||||
goto not_baz4;
|
goto not_baz4;
|
||||||
} else {
|
} else {
|
||||||
return $this->redirect($rawPathinfo.'/', 'baz4');
|
return $this->redirect($rawPathinfo.'/', 'baz4');
|
||||||
@ -183,6 +185,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
|||||||
if ('/' === substr($pathinfo, -1)) {
|
if ('/' === substr($pathinfo, -1)) {
|
||||||
// no-op
|
// no-op
|
||||||
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||||
|
$allow[] = 'GET';
|
||||||
goto not_hey;
|
goto not_hey;
|
||||||
} else {
|
} else {
|
||||||
return $this->redirect($rawPathinfo.'/', 'hey');
|
return $this->redirect($rawPathinfo.'/', 'hey');
|
||||||
@ -333,21 +336,33 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
|||||||
if ('/secure' === $pathinfo) {
|
if ('/secure' === $pathinfo) {
|
||||||
$requiredSchemes = array ( 'https' => 0,);
|
$requiredSchemes = array ( 'https' => 0,);
|
||||||
if (!isset($requiredSchemes[$this->context->getScheme()])) {
|
if (!isset($requiredSchemes[$this->context->getScheme()])) {
|
||||||
|
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||||
|
$allow[] = 'GET';
|
||||||
|
goto not_secure;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->redirect($rawPathinfo, 'secure', key($requiredSchemes));
|
return $this->redirect($rawPathinfo, 'secure', key($requiredSchemes));
|
||||||
}
|
}
|
||||||
|
|
||||||
return array('_route' => 'secure');
|
return array('_route' => 'secure');
|
||||||
}
|
}
|
||||||
|
not_secure:
|
||||||
|
|
||||||
// nonsecure
|
// nonsecure
|
||||||
if ('/nonsecure' === $pathinfo) {
|
if ('/nonsecure' === $pathinfo) {
|
||||||
$requiredSchemes = array ( 'http' => 0,);
|
$requiredSchemes = array ( 'http' => 0,);
|
||||||
if (!isset($requiredSchemes[$this->context->getScheme()])) {
|
if (!isset($requiredSchemes[$this->context->getScheme()])) {
|
||||||
|
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
|
||||||
|
$allow[] = 'GET';
|
||||||
|
goto not_nonsecure;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes));
|
return $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes));
|
||||||
}
|
}
|
||||||
|
|
||||||
return array('_route' => 'nonsecure');
|
return array('_route' => 'nonsecure');
|
||||||
}
|
}
|
||||||
|
not_nonsecure:
|
||||||
|
|
||||||
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,14 @@ use Symfony\Component\Routing\RequestContext;
|
|||||||
|
|
||||||
class DumpedRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest
|
class DumpedRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Routing\Exception\MethodNotAllowedException
|
||||||
|
*/
|
||||||
|
public function testRedirectWhenNoSlashForNonSafeMethod()
|
||||||
|
{
|
||||||
|
parent::testRedirectWhenNoSlashForNonSafeMethod();
|
||||||
|
}
|
||||||
|
|
||||||
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
||||||
{
|
{
|
||||||
static $i = 0;
|
static $i = 0;
|
||||||
|
Reference in New Issue
Block a user