Skip to content

Commit 952388c

Browse files
committed
[Routing] make host matching case-insensitive according to RFC 3986
1 parent 6000f60 commit 952388c

File tree

8 files changed

+48
-20
lines changed

8 files changed

+48
-20
lines changed

src/Symfony/Component/Routing/Generator/UrlGenerator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
213213
$routeHost = '';
214214
foreach ($hostTokens as $token) {
215215
if ('variable' === $token[0]) {
216-
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) {
216+
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i', $mergedParams[$token[3]])) {
217217
$message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]);
218218

219219
if ($this->strictRequirements) {

src/Symfony/Component/Routing/RouteCompiler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static function compile(Route $route)
4646
$result = self::compilePattern($route, $host, true);
4747

4848
$hostVariables = $result['variables'];
49-
$variables = array_merge($variables, $hostVariables);
49+
$variables = $hostVariables;
5050

5151
$hostTokens = $result['tokens'];
5252
$hostRegex = $result['regex'];
@@ -163,7 +163,7 @@ private static function compilePattern(Route $route, $pattern, $isHost)
163163

164164
return array(
165165
'staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '',
166-
'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s',
166+
'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s'.($isHost ? 'i' : ''),
167167
'tokens' => array_reverse($tokens),
168168
'variables' => $variables,
169169
);

src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ public function match($pathinfo)
195195

196196
$host = $this->context->getHost();
197197

198-
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
198+
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
199199
// route1
200200
if ($pathinfo === '/route1') {
201201
return array('_route' => 'route1');
@@ -208,23 +208,23 @@ public function match($pathinfo)
208208

209209
}
210210

211-
if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) {
211+
if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) {
212212
// route3
213213
if ($pathinfo === '/c2/route3') {
214214
return array('_route' => 'route3');
215215
}
216216

217217
}
218218

219-
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
219+
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
220220
// route4
221221
if ($pathinfo === '/route4') {
222222
return array('_route' => 'route4');
223223
}
224224

225225
}
226226

227-
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
227+
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
228228
// route5
229229
if ($pathinfo === '/route5') {
230230
return array('_route' => 'route5');
@@ -237,7 +237,7 @@ public function match($pathinfo)
237237
return array('_route' => 'route6');
238238
}
239239

240-
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) {
240+
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) {
241241
if (0 === strpos($pathinfo, '/route1')) {
242242
// route11
243243
if ($pathinfo === '/route11') {
@@ -263,7 +263,7 @@ public function match($pathinfo)
263263

264264
}
265265

266-
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
266+
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
267267
// route15
268268
if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
269269
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());

src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ public function match($pathinfo)
207207

208208
$host = $this->context->getHost();
209209

210-
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
210+
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
211211
// route1
212212
if ($pathinfo === '/route1') {
213213
return array('_route' => 'route1');
@@ -220,23 +220,23 @@ public function match($pathinfo)
220220

221221
}
222222

223-
if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) {
223+
if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) {
224224
// route3
225225
if ($pathinfo === '/c2/route3') {
226226
return array('_route' => 'route3');
227227
}
228228

229229
}
230230

231-
if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) {
231+
if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) {
232232
// route4
233233
if ($pathinfo === '/route4') {
234234
return array('_route' => 'route4');
235235
}
236236

237237
}
238238

239-
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
239+
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
240240
// route5
241241
if ($pathinfo === '/route5') {
242242
return array('_route' => 'route5');
@@ -249,7 +249,7 @@ public function match($pathinfo)
249249
return array('_route' => 'route6');
250250
}
251251

252-
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) {
252+
if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) {
253253
if (0 === strpos($pathinfo, '/route1')) {
254254
// route11
255255
if ($pathinfo === '/route11') {
@@ -275,7 +275,7 @@ public function match($pathinfo)
275275

276276
}
277277

278-
if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) {
278+
if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) {
279279
// route15
280280
if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) {
281281
return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ());

src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,13 @@ public function testUrlWithInvalidParameterInHostInNonStrictMode()
443443
$this->assertNull($generator->generate('test', array('foo' => 'baz'), false));
444444
}
445445

446+
public function testHostIsCaseInsensitive()
447+
{
448+
$routes = $this->getRoutes('test', new Route('/', array(), array('locale' => 'en|de|fr'), array(), '{locale}.FooBar.com'));
449+
$generator = $this->getGenerator($routes);
450+
$this->assertSame('//EN.FooBar.com/app.php/', $generator->generate('test', array('locale' => 'EN'), UrlGeneratorInterface::NETWORK_PATH));
451+
}
452+
446453
public function testGenerateNetworkPath()
447454
{
448455
$routes = $this->getRoutes('test', new Route('/{name}', array(), array('_scheme' => 'http'), array(), '{locale}.example.com'));

src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,25 @@ public function testWithOutHostHostDoesNotMatch()
382382
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'example.com'));
383383
$matcher->match('/foo/bar');
384384
}
385+
386+
/**
387+
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
388+
*/
389+
public function testPathIsCaseSensitive()
390+
{
391+
$coll = new RouteCollection();
392+
$coll->add('foo', new Route('/locale', array(), array('locale' => 'EN|FR|DE')));
393+
394+
$matcher = new UrlMatcher($coll, new RequestContext());
395+
$matcher->match('/en');
396+
}
397+
398+
public function testHostIsCaseInsensitive()
399+
{
400+
$coll = new RouteCollection();
401+
$coll->add('foo', new Route('/', array(), array('locale' => 'EN|FR|DE'), array(), '{locale}.example.com'));
402+
403+
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
404+
$this->assertEquals(array('_route' => 'foo', 'locale' => 'en'), $matcher->match('/'));
405+
}
385406
}

src/Symfony/Component/Routing/Tests/RouteCompilerTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ public function provideCompileWithHostData()
208208
'/hello', '#^/hello$#s', array(), array(), array(
209209
array('text', '/hello'),
210210
),
211-
'#^www\.example\.com$#s', array(), array(
211+
'#^www\.example\.com$#si', array(), array(
212212
array('text', 'www.example.com'),
213213
),
214214
),
@@ -219,7 +219,7 @@ public function provideCompileWithHostData()
219219
array('variable', '/', '[^/]++', 'name'),
220220
array('text', '/hello'),
221221
),
222-
'#^www\.example\.(?P<tld>[^\.]++)$#s', array('tld'), array(
222+
'#^www\.example\.(?P<tld>[^\.]++)$#si', array('tld'), array(
223223
array('variable', '.', '[^\.]++', 'tld'),
224224
array('text', 'www.example'),
225225
),
@@ -230,7 +230,7 @@ public function provideCompileWithHostData()
230230
'/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
231231
array('text', '/hello'),
232232
),
233-
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array(
233+
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
234234
array('variable', '.', '[^\.]++', 'tld'),
235235
array('text', '.example'),
236236
array('variable', '', '[^\.]++', 'locale'),
@@ -242,7 +242,7 @@ public function provideCompileWithHostData()
242242
'/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
243243
array('text', '/hello'),
244244
),
245-
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array(
245+
'#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
246246
array('variable', '.', '[^\.]++', 'tld'),
247247
array('text', '.example'),
248248
array('variable', '', '[^\.]++', 'locale'),

src/Symfony/Component/Routing/Tests/RouteTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ public function testSerializeWhenCompiled()
247247
*/
248248
public function testSerializedRepresentationKeepsWorking()
249249
{
250-
$serialized = 'C:31:"Symfony\Component\Routing\Route":933:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":568:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:30:"#^/prefix(?:/(?P<foo>\d+))?$#s";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:38:"#^(?P<locale>[^\.]++)\.example\.net$#s";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}';
250+
$serialized = 'C:31:"Symfony\Component\Routing\Route":934:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":569:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:30:"#^/prefix(?:/(?P<foo>\d+))?$#s";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:39:"#^(?P<locale>[^\.]++)\.example\.net$#si";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}';
251251
$unserialized = unserialize($serialized);
252252

253253
$route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+'));

0 commit comments

Comments
 (0)