[Routing] dont redirect routes with greedy trailing vars with no explicit slash

This commit is contained in:
Nicolas Grekas 2019-01-29 08:59:09 +01:00
parent 78c23c7838
commit 2bb8890bbb
13 changed files with 80 additions and 213 deletions

View File

@ -558,34 +558,27 @@ EOF;
$code = '';
}
$code .= $hasVars ? '
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}' : '
break;';
$code = sprintf(<<<'EOF'
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {%s
if ('/' !== $pathinfo && %s$hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {%s
break;
}
EOF
,
$hasVars ? '!$hasTrailingVar && ' : '',
$code
);
if ($hasVars) {
$code = <<<'EOF'
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
EOF
.$code.<<<'EOF'
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {
if (isset($matches[1 + $i])) {
@ -665,31 +658,10 @@ EOF
if ('/' !== $pathinfo && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
EOF;
} elseif ($this->supportsRedirections && (!$methods || isset($methods['GET']))) {
$code .= <<<'EOF'
$hasTrailingSlash = false;
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {%s
if ($trimmedPathinfo === $pathinfo) {
goto %s;
}
}
EOF;
} else {
$code .= <<<'EOF'
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} elseif ('/' !== $pathinfo) {
if ($trimmedPathinfo !== $pathinfo) {
goto %2$s;
}
EOF;

View File

@ -156,21 +156,18 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
continue;
}
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar = preg_match('#\{\w+\}/?$#', $route->getPath())) {
// no-op
} elseif (preg_match($regex, $trimmedPathinfo, $m)) {
$matches = $m;
} else {
$hasTrailingSlash = true;
}
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath());
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) {
return $this->allow = $this->allowSchemes = [];
}
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
continue;
}
continue;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, $trimmedPathinfo, $m)) {
$matches = $m;
}
$hostMatches = [];

View File

@ -187,11 +187,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
break;
case 160:
// foo1
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} elseif ('/' !== $pathinfo) {
if ($trimmedPathinfo !== $pathinfo) {
goto not_foo1;
}
@ -209,11 +205,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
break;
case 204:
// foo2
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} elseif ('/' !== $pathinfo) {
if ($trimmedPathinfo !== $pathinfo) {
goto not_foo2;
}
@ -225,11 +217,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
break;
case 279:
// foo3
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} elseif ('/' !== $pathinfo) {
if ($trimmedPathinfo !== $pathinfo) {
goto not_foo3;
}
@ -262,17 +250,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
break;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -2794,17 +2794,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
break;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -119,20 +119,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ('GET' === $canonicalMethod && (!$requiredMethods || isset($requiredMethods['GET']))) {
return $allow = $allowSchemes = [];
}
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -64,17 +64,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
break;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -44,11 +44,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
switch ($m = (int) $matches['MARK']) {
case 56:
// r1
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} elseif ('/' !== $pathinfo) {
if ($trimmedPathinfo !== $pathinfo) {
goto not_r1;
}
@ -58,11 +54,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
not_r1:
// r2
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} elseif ('/' !== $pathinfo) {
if ($trimmedPathinfo !== $pathinfo) {
goto not_r2;
}

View File

@ -230,11 +230,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
break;
case 160:
// foo1
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} elseif ('/' !== $pathinfo) {
if ($trimmedPathinfo !== $pathinfo) {
goto not_foo1;
}
@ -252,22 +248,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
break;
case 204:
// foo2
$hasTrailingSlash = false;
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ('GET' === $canonicalMethod) {
return $allow = $allowSchemes = [];
}
if ($trimmedPathinfo === $pathinfo) {
goto not_foo2;
}
if ($trimmedPathinfo !== $pathinfo) {
goto not_foo2;
}
$matches = ['foo1' => $matches[1] ?? null];
@ -278,22 +260,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
break;
case 279:
// foo3
$hasTrailingSlash = false;
if ($trimmedPathinfo === $pathinfo) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ('GET' === $canonicalMethod) {
return $allow = $allowSchemes = [];
}
if ($trimmedPathinfo === $pathinfo) {
goto not_foo3;
}
if ($trimmedPathinfo !== $pathinfo) {
goto not_foo3;
}
$matches = ['_locale' => $matches[1] ?? null, 'foo' => $matches[2] ?? null];
@ -325,20 +293,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ('GET' === $canonicalMethod && (!$requiredMethods || isset($requiredMethods['GET']))) {
return $allow = $allowSchemes = [];
}
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -84,17 +84,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
break;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -124,20 +124,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ('GET' === $canonicalMethod && (!$requiredMethods || isset($requiredMethods['GET']))) {
return $allow = $allowSchemes = [];
}
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -98,17 +98,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
break;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -136,20 +136,15 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ('GET' === $canonicalMethod && (!$requiredMethods || isset($requiredMethods['GET']))) {
return $allow = $allowSchemes = [];
}
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {

View File

@ -52,17 +52,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar) = $routes[$m];
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
// no-op
} elseif (preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
} else {
$hasTrailingSlash = true;
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
break;
}
if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) {
if ($trimmedPathinfo === $pathinfo || !$hasTrailingVar) {
break;
}
if ($hasTrailingSlash && $hasTrailingVar && preg_match($regex, rtrim($matchedPathinfo, '/') ?: '/', $n) && $m === (int) $n['MARK']) {
$matches = $n;
}
foreach ($vars as $i => $v) {