Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[Routing] added support for hostname in the apache matcher dumper

  • Loading branch information...
commit a8ce6210b37d4d1d41c1c6fa26bd627b1a11b597 1 parent 562174a
@arnaud-lb arnaud-lb authored
View
77 src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php
@@ -46,17 +46,55 @@ public function dump(array $options = array())
$rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]");
$methodVars = array();
+ $hostnameRegexUnique = 0;
+ $prevHosnameRegex = '';
foreach ($this->getRoutes()->all() as $name => $route) {
- $rules[] = $this->dumpRoute($name, $route, $options);
- $methodVars = array_merge($methodVars, $this->getRouteMethods($route));
- }
+ $compiledRoute = $route->compile();
+ $hostnameRegex = $compiledRoute->getHostnameRegex();
+
+ if (null !== $hostnameRegex && $prevHosnameRegex !== $hostnameRegex) {
+
+ $prevHosnameRegex = $hostnameRegex;
+ $hostnameRegexUnique++;
+
+ $rule = array();
+
+ $regex = $this->regexToApacheRegex($hostnameRegex);
+ $regex = self::escape($regex, ' ', '\\');
+
+ $rule[] = sprintf('RewriteCond %%{HTTP:Host} %s', $regex);
+
+ $variables = array();
+ $variables[] = sprintf('E=__ROUTING_hostname_%s:1', $hostnameRegexUnique);
+
+ foreach ($compiledRoute->getHostnameVariables() as $i => $variable) {
+ $variables[] = sprintf('E=__ROUTING_hostname_%s_%s:%%%d', $hostnameRegexUnique, $variable, $i+1);
+ }
+
+ $variables = implode(',', $variables);
+
+ $rule[] = sprintf('RewriteRule .? - [%s]', $variables);
+
+ $rules[] = implode("\n", $rule);
+ }
+
+ $rules[] = $this->dumpRoute($name, $route, $options, $hostnameRegexUnique);
+
+ if ($req = $route->getRequirement('_method')) {
+ $methods = explode('|', strtoupper($req));
+ $methodVars = array_merge($methodVars, $methods);
+ }
+ }
if (0 < count($methodVars)) {
$rule = array('# 405 Method Not Allowed');
$methodVars = array_values(array_unique($methodVars));
+ if (in_array('GET', $methodVars) && !in_array('HEAD', $methodVars)) {
+ $methodVars[] = 'HEAD';
+ }
foreach ($methodVars as $i => $methodVar) {
- $rule[] = sprintf('RewriteCond %%{_ROUTING_allow_%s} !-z%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : '');
+ $rule[] = sprintf('RewriteCond %%{ENV:_ROUTING__allow_%s} =1%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : '');
}
$rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']);
@@ -66,7 +104,16 @@ public function dump(array $options = array())
return implode("\n\n", $rules)."\n";
}
- private function dumpRoute($name, $route, array $options)
+ /**
+ * Dumps a single route
+ *
+ * @param string $name Route name
+ * @param Route $route The route
+ * @param array $options Options
+ * @param bool $hostnameRegexUnique Unique identifier for the hostname regex
+ * @return string The compiled route
+ */
+ private function dumpRoute($name, $route, array $options, $hostnameRegexUnique)
{
$compiledRoute = $route->compile();
@@ -79,7 +126,10 @@ private function dumpRoute($name, $route, array $options)
$hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex;
$variables = array('E=_ROUTING_route:'.$name);
- foreach ($compiledRoute->getVariables() as $i => $variable) {
+ foreach ($compiledRoute->getHostnameVariables() as $variable) {
+ $variables[] = sprintf('E=_ROUTING_param_%s:%%{ENV:__ROUTING_hostname_%s_%s}', $variable, $hostnameRegexUnique, $variable);
+ }
+ foreach ($compiledRoute->getPathVariables() as $i => $variable) {
$variables[] = 'E=_ROUTING_param_'.$variable.':%'.($i + 1);
}
foreach ($route->getDefaults() as $key => $value) {
@@ -98,10 +148,13 @@ private function dumpRoute($name, $route, array $options)
if (0 < count($methods)) {
$allow = array();
foreach ($methods as $method) {
- $methodVars[] = $method;
$allow[] = 'E=_ROUTING_allow_'.$method.':1';
}
+ if ($hostnameRegex = $compiledRoute->getHostnameRegex()) {
+ $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_hostname_%s} =1", $hostnameRegexUnique);
+ }
+
$rule[] = "RewriteCond %{REQUEST_URI} $regex";
$rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods));
$rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow));
@@ -109,11 +162,21 @@ private function dumpRoute($name, $route, array $options)
// redirect with trailing slash appended
if ($hasTrailingSlash) {
+
+ if ($hostnameRegex = $compiledRoute->getHostnameRegex()) {
+ $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_hostname_%s} =1", $hostnameRegexUnique);
+ }
+
$rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$';
$rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]';
}
// the main rule
+
+ if ($hostnameRegex = $compiledRoute->getHostnameRegex()) {
+ $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_hostname_%s} =1", $hostnameRegexUnique);
+ }
+
$rule[] = "RewriteCond %{REQUEST_URI} $regex";
$rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]";
View
94 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache
@@ -68,8 +68,96 @@ RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz6,E=_ROUTING_default_foo:bar\
RewriteCond %{REQUEST_URI} ^/te\ st/baz$
RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz7]
+# baz8
+RewriteCond %{REQUEST_URI} ^/te\\\ st/baz$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz8]
+
+# baz9
+RewriteCond %{REQUEST_URI} ^/test/(te\\\ st)$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz9,E=_ROUTING_param_baz:%1]
+
+RewriteCond %{HTTP:Host} ^a\.example\.com$
+RewriteRule .? - [E=__ROUTING_hostname_1:1]
+
+# route1
+RewriteCond %{ENV:__ROUTING_hostname_1} =1
+RewriteCond %{REQUEST_URI} ^/route1$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route1]
+
+# route2
+RewriteCond %{ENV:__ROUTING_hostname_1} =1
+RewriteCond %{REQUEST_URI} ^/c2/route2$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route2]
+
+RewriteCond %{HTTP:Host} ^b\.example\.com$
+RewriteRule .? - [E=__ROUTING_hostname_2:1]
+
+# route3
+RewriteCond %{ENV:__ROUTING_hostname_2} =1
+RewriteCond %{REQUEST_URI} ^/c2/route3$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route3]
+
+RewriteCond %{HTTP:Host} ^a\.example\.com$
+RewriteRule .? - [E=__ROUTING_hostname_3:1]
+
+# route4
+RewriteCond %{ENV:__ROUTING_hostname_3} =1
+RewriteCond %{REQUEST_URI} ^/route4$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route4]
+
+RewriteCond %{HTTP:Host} ^c\.example\.com$
+RewriteRule .? - [E=__ROUTING_hostname_4:1]
+
+# route5
+RewriteCond %{ENV:__ROUTING_hostname_4} =1
+RewriteCond %{REQUEST_URI} ^/route5$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route5]
+
+# route6
+RewriteCond %{REQUEST_URI} ^/route6$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route6]
+
+RewriteCond %{HTTP:Host} ^([^\.]++)\.example\.com$
+RewriteRule .? - [E=__ROUTING_hostname_5:1,E=__ROUTING_hostname_5_var1:%1]
+
+# route11
+RewriteCond %{ENV:__ROUTING_hostname_5} =1
+RewriteCond %{REQUEST_URI} ^/route11$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route11,E=_ROUTING_param_var1:%{ENV:__ROUTING_hostname_5_var1}]
+
+# route12
+RewriteCond %{ENV:__ROUTING_hostname_5} =1
+RewriteCond %{REQUEST_URI} ^/route12$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route12,E=_ROUTING_param_var1:%{ENV:__ROUTING_hostname_5_var1},E=_ROUTING_default_var1:val]
+
+# route13
+RewriteCond %{ENV:__ROUTING_hostname_5} =1
+RewriteCond %{REQUEST_URI} ^/route13/([^/]++)$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route13,E=_ROUTING_param_var1:%{ENV:__ROUTING_hostname_5_var1},E=_ROUTING_param_name:%1]
+
+# route14
+RewriteCond %{ENV:__ROUTING_hostname_5} =1
+RewriteCond %{REQUEST_URI} ^/route14/([^/]++)$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route14,E=_ROUTING_param_var1:%{ENV:__ROUTING_hostname_5_var1},E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val]
+
+RewriteCond %{HTTP:Host} ^c\.example\.com$
+RewriteRule .? - [E=__ROUTING_hostname_6:1]
+
+# route15
+RewriteCond %{ENV:__ROUTING_hostname_6} =1
+RewriteCond %{REQUEST_URI} ^/route15/([^/]++)$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route15,E=_ROUTING_param_name:%1]
+
+# route16
+RewriteCond %{REQUEST_URI} ^/route16/([^/]++)$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route16,E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val]
+
+# route17
+RewriteCond %{REQUEST_URI} ^/route17$
+RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route17]
+
# 405 Method Not Allowed
-RewriteCond %{_ROUTING_allow_GET} !-z [OR]
-RewriteCond %{_ROUTING_allow_HEAD} !-z [OR]
-RewriteCond %{_ROUTING_allow_POST} !-z
+RewriteCond %{ENV:_ROUTING__allow_GET} =1 [OR]
+RewriteCond %{ENV:_ROUTING__allow_HEAD} =1 [OR]
+RewriteCond %{ENV:_ROUTING__allow_POST} =1
RewriteRule .* app.php [QSA,L]
View
14 src/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php
@@ -118,6 +118,20 @@ public function getMatchData()
'_route' => 'hello',
),
),
+ array(
+ 'REDIRECT_REDIRECT_ envs',
+ '/hello/world',
+ array(
+ 'REDIRECT_REDIRECT__ROUTING_route' => 'hello',
+ 'REDIRECT_REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index',
+ 'REDIRECT_REDIRECT__ROUTING_param_name' => 'world',
+ ),
+ array(
+ '_controller' => 'AcmeBundle:Default:index',
+ 'name' => 'world',
+ '_route' => 'hello',
+ ),
+ ),
);
}
}
View
65 src/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php
@@ -124,6 +124,71 @@ private function getRouteCollection()
$collection->add('baz7', new Route(
'/te st/baz'
));
+ // space preceded with \ in path
+ $collection->add('baz8', new Route(
+ '/te\\ st/baz'
+ ));
+ // space preceded with \ in requirement
+ $collection->add('baz9', new Route(
+ '/test/{baz}',
+ array(),
+ array(
+ 'baz' => 'te\\\\ st',
+ )
+ ));
+
+ $collection1 = new RouteCollection();
+
+ $route1 = new Route('/route1', array(), array(), array(), 'a.example.com');
+ $collection1->add('route1', $route1);
+
+ $collection2 = new RouteCollection();
+
+ $route2 = new Route('/route2', array(), array(), array(), 'a.example.com');
+ $collection2->add('route2', $route2);
+
+ $route3 = new Route('/route3', array(), array(), array(), 'b.example.com');
+ $collection2->add('route3', $route3);
+
+ $collection1->addCollection($collection2, '/c2');
+
+ $route4 = new Route('/route4', array(), array(), array(), 'a.example.com');
+ $collection1->add('route4', $route4);
+
+ $route5 = new Route('/route5', array(), array(), array(), 'c.example.com');
+ $collection1->add('route5', $route5);
+
+ $route6 = new Route('/route6', array(), array(), array(), null);
+ $collection1->add('route6', $route6);
+
+ $collection->addCollection($collection1);
+
+ // hostname and variables
+
+ $collection1 = new RouteCollection();
+
+ $route11 = new Route('/route11', array(), array(), array(), '{var1}.example.com');
+ $collection1->add('route11', $route11);
+
+ $route12 = new Route('/route12', array('var1' => 'val'), array(), array(), '{var1}.example.com');
+ $collection1->add('route12', $route12);
+
+ $route13 = new Route('/route13/{name}', array(), array(), array(), '{var1}.example.com');
+ $collection1->add('route13', $route13);
+
+ $route14 = new Route('/route14/{name}', array('var1' => 'val'), array(), array(), '{var1}.example.com');
+ $collection1->add('route14', $route14);
+
+ $route15 = new Route('/route15/{name}', array(), array(), array(), 'c.example.com');
+ $collection1->add('route15', $route15);
+
+ $route16 = new Route('/route16/{name}', array('var1' => 'val'), array(), array(), null);
+ $collection1->add('route16', $route16);
+
+ $route17 = new Route('/route17', array(), array(), array(), null);
+ $collection1->add('route17', $route17);
+
+ $collection->addCollection($collection1);
return $collection;
}
Please sign in to comment.
Something went wrong with that request. Please try again.