[Routing] removed trailing slash support for routes that are not available for GET/HEAD methods (as the redirection will always occurs with a GET/HEAD request, closes #2626)
This commit is contained in:
parent
7b00662df3
commit
d12f5b202c
@ -49,7 +49,16 @@ class ApacheMatcherDumper extends MatcherDumper
|
||||
$regex = preg_replace('/\?P<.+?>/', '', substr(str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), 1, -3));
|
||||
$regex = '^'.preg_quote($options['base_uri']).substr($regex, 1);
|
||||
|
||||
$hasTrailingSlash = '/$' == substr($regex, -2) && '^/$' != $regex;
|
||||
$methods = array();
|
||||
if ($req = $route->getRequirement('_method')) {
|
||||
$methods = explode('|', strtoupper($req));
|
||||
// GET and HEAD are equivalent
|
||||
if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
|
||||
$methods[] = 'HEAD';
|
||||
}
|
||||
}
|
||||
|
||||
$hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' == substr($regex, -2) && '^/$' != $regex;
|
||||
|
||||
$variables = array('E=_ROUTING__route:'.$name);
|
||||
foreach ($compiledRoute->getVariables() as $i => $variable) {
|
||||
|
@ -148,8 +148,18 @@ EOF;
|
||||
$conditions = array();
|
||||
$hasTrailingSlash = false;
|
||||
$matches = false;
|
||||
$methods = array();
|
||||
if ($req = $route->getRequirement('_method')) {
|
||||
$methods = explode('|', strtoupper($req));
|
||||
// GET and HEAD are equivalent
|
||||
if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
|
||||
$methods[] = 'HEAD';
|
||||
}
|
||||
}
|
||||
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods));
|
||||
|
||||
if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', str_replace(array("\n", ' '), '', $compiledRoute->getRegex()), $m)) {
|
||||
if ($supportsRedirections && substr($m['url'], -1) === '/') {
|
||||
if ($supportsTrailingSlash && substr($m['url'], -1) === '/') {
|
||||
$conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true));
|
||||
$hasTrailingSlash = true;
|
||||
} else {
|
||||
@ -161,7 +171,7 @@ EOF;
|
||||
}
|
||||
|
||||
$regex = str_replace(array("\n", ' '), '', $compiledRoute->getRegex());
|
||||
if ($supportsRedirections && $pos = strpos($regex, '/$')) {
|
||||
if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) {
|
||||
$regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2);
|
||||
$hasTrailingSlash = true;
|
||||
}
|
||||
@ -179,12 +189,7 @@ EOF;
|
||||
if ($conditions) {
|
||||
EOF;
|
||||
|
||||
if ($req = $route->getRequirement('_method')) {
|
||||
$methods = explode('|', strtoupper($req));
|
||||
// GET and HEAD are equivalent
|
||||
if (in_array('GET', $methods) && !in_array('HEAD', $methods)) {
|
||||
$methods[] = 'HEAD';
|
||||
}
|
||||
if ($methods) {
|
||||
if (1 === count($methods)) {
|
||||
$code[] = <<<EOF
|
||||
if (\$this->context->getMethod() != '$methods[0]') {
|
||||
@ -239,7 +244,7 @@ EOF
|
||||
}
|
||||
$code[] = " }";
|
||||
|
||||
if ($req) {
|
||||
if ($methods) {
|
||||
$code[] = " $gotoname:";
|
||||
}
|
||||
|
||||
|
@ -42,13 +42,20 @@ RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz4,E=_ROUTING_foo:%1]
|
||||
|
||||
# baz5
|
||||
RewriteCond %{REQUEST_URI} ^/test/([^/]+?)/$
|
||||
RewriteCond %{REQUEST_METHOD} !^(POST)$ [NC]
|
||||
RewriteRule .* - [S=2,E=_ROUTING__allow_POST:1]
|
||||
RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC]
|
||||
RewriteRule .* - [S=2,E=_ROUTING__allow_GET:1,E=_ROUTING__allow_HEAD:1]
|
||||
RewriteCond %{REQUEST_URI} ^/test/([^/]+?)$
|
||||
RewriteRule .* $0/ [QSA,L,R=301]
|
||||
RewriteCond %{REQUEST_URI} ^/test/([^/]+?)/$
|
||||
RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz5,E=_ROUTING_foo:%1]
|
||||
|
||||
# baz5unsafe
|
||||
RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]+?)/$
|
||||
RewriteCond %{REQUEST_METHOD} !^(POST)$ [NC]
|
||||
RewriteRule .* - [S=1,E=_ROUTING__allow_POST:1]
|
||||
RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]+?)/$
|
||||
RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz5unsafe,E=_ROUTING_foo:%1]
|
||||
|
||||
# baz6
|
||||
RewriteCond %{REQUEST_URI} ^/test/baz$
|
||||
RewriteRule .* app.php [QSA,L,E=_ROUTING__route:baz6,E=_ROUTING_foo:bar\ baz]
|
||||
|
@ -80,28 +80,22 @@ class ProjectUrlMatcher extends Symfony\Tests\Component\Routing\Fixtures\Redirec
|
||||
}
|
||||
|
||||
// baz5
|
||||
if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/?$#xs', $pathinfo, $matches)) {
|
||||
if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#xs', $pathinfo, $matches)) {
|
||||
if ($this->context->getMethod() != 'POST') {
|
||||
$allow[] = 'POST';
|
||||
goto not_baz5;
|
||||
}
|
||||
if (substr($pathinfo, -1) !== '/') {
|
||||
return $this->redirect($pathinfo.'/', 'baz5');
|
||||
}
|
||||
$matches['_route'] = 'baz5';
|
||||
return $matches;
|
||||
}
|
||||
not_baz5:
|
||||
|
||||
// baz.baz6
|
||||
if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/?$#xs', $pathinfo, $matches)) {
|
||||
if (0 === strpos($pathinfo, '/test') && preg_match('#^/test/(?P<foo>[^/]+?)/$#xs', $pathinfo, $matches)) {
|
||||
if ($this->context->getMethod() != 'PUT') {
|
||||
$allow[] = 'PUT';
|
||||
goto not_bazbaz6;
|
||||
}
|
||||
if (substr($pathinfo, -1) !== '/') {
|
||||
return $this->redirect($pathinfo.'/', 'baz.baz6');
|
||||
}
|
||||
$matches['_route'] = 'baz.baz6';
|
||||
return $matches;
|
||||
}
|
||||
|
@ -62,10 +62,16 @@ class ApacheMatcherDumperTest extends \PHPUnit_Framework_TestCase
|
||||
$collection->add('baz4', new Route(
|
||||
'/test/{foo}/'
|
||||
));
|
||||
// trailing slash and method
|
||||
// trailing slash and safe method
|
||||
$collection->add('baz5', new Route(
|
||||
'/test/{foo}/',
|
||||
array(),
|
||||
array('_method' => 'get')
|
||||
));
|
||||
// trailing slash and unsafe method
|
||||
$collection->add('baz5unsafe', new Route(
|
||||
'/testunsafe/{foo}/',
|
||||
array(),
|
||||
array('_method' => 'post')
|
||||
));
|
||||
// complex
|
||||
|
Reference in New Issue
Block a user