Skip to content

Commit d86e1eb

Browse files
committed
[Routing] Remove a weird dependency
1 parent 11e3516 commit d86e1eb

File tree

4 files changed

+63
-22
lines changed

4 files changed

+63
-22
lines changed

CHANGELOG-2.1.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
242242

243243
### Routing
244244

245+
* the UrlMatcher does not throw a \LogicException any more when the required scheme is not the current one
245246
* added a TraceableUrlMatcher
246247
* added the possibility to define default values and requirements for placeholders in prefix, including imported routes
247248
* added RouterInterface::getRouteCollection

src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Routing\Matcher;
1313

1414
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
15+
use Symfony\Component\Routing\Route;
1516

1617
/**
1718
* @author Fabien Potencier <fabien@symfony.com>
@@ -20,8 +21,6 @@
2021
*/
2122
abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
2223
{
23-
private $trailingSlashTest = false;
24-
2524
/**
2625
* @see UrlMatcher::match()
2726
*
@@ -36,18 +35,28 @@ public function match($pathinfo)
3635
throw $e;
3736
}
3837

39-
// try with a / at the end
40-
$this->trailingSlashTest = true;
41-
42-
return $this->match($pathinfo.'/');
38+
try {
39+
parent::match($pathinfo.'/');
40+
return $this->redirect($pathinfo.'/', null);
41+
} catch (ResourceNotFoundException $e2) {
42+
throw $e;
43+
}
4344
}
4445

45-
if ($this->trailingSlashTest) {
46-
$this->trailingSlashTest = false;
46+
return $parameters;
47+
}
4748

48-
return $this->redirect($pathinfo, null);
49+
/**
50+
* {@inheritDoc}
51+
*/
52+
protected function handleRouteRequirements($pathinfo, $name, Route $route)
53+
{
54+
// check HTTP scheme requirement
55+
$scheme = $route->getRequirement('_scheme');
56+
if ($scheme && $this->context->getScheme() !== $scheme) {
57+
return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, $scheme));
4958
}
5059

51-
return $parameters;
60+
return array(self::REQUIREMENT_MATCH, null);
5261
}
5362
}

src/Symfony/Component/Routing/Matcher/UrlMatcher.php

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
1616
use Symfony\Component\Routing\RouteCollection;
1717
use Symfony\Component\Routing\RequestContext;
18-
use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface;
18+
use Symfony\Component\Routing\Route;
1919

2020
/**
2121
* UrlMatcher matches URL based on a set of routes.
@@ -26,6 +26,10 @@
2626
*/
2727
class UrlMatcher implements UrlMatcherInterface
2828
{
29+
const REQUIREMENT_MATCH = 0;
30+
const REQUIREMENT_MISMATCH = 1;
31+
const ROUTE_MATCH = 2;
32+
2933
protected $context;
3034

3135
private $routes;
@@ -84,6 +88,17 @@ public function match($pathinfo)
8488
: new ResourceNotFoundException();
8589
}
8690

91+
/**
92+
* Tries to match a URL with a set of routes.
93+
*
94+
* @param string $pathinfo The path info to be parsed
95+
* @param RouteCollection $routes The set of routes
96+
*
97+
* @return array An array of parameters
98+
*
99+
* @throws ResourceNotFoundException If the resource could not be found
100+
* @throws MethodNotAllowedException If the resource was found but the request method is not allowed
101+
*/
87102
protected function matchCollection($pathinfo, RouteCollection $routes)
88103
{
89104
$pathinfo = urldecode($pathinfo);
@@ -126,21 +141,38 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
126141
}
127142
}
128143

129-
// check HTTP scheme requirement
130-
if ($scheme = $route->getRequirement('_scheme')) {
131-
if (!$this instanceof RedirectableUrlMatcherInterface) {
132-
throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
133-
}
144+
$status = $this->handleRouteRequirements($pathinfo, $name, $route);
134145

135-
if ($this->context->getScheme() !== $scheme) {
136-
return $this->redirect($pathinfo, $name, $scheme);
137-
}
146+
if (self::ROUTE_MATCH === $status[0]) {
147+
return $status[1];
148+
}
149+
150+
if (self::REQUIREMENT_MISMATCH === $status[0]) {
151+
continue;
138152
}
139153

140154
return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $name));
141155
}
142156
}
143157

158+
/**
159+
* Handles specific route requirements.
160+
*
161+
* @param string $pathinfo The path
162+
* @param string $name The route name
163+
* @param string $route The route
164+
*
165+
* @return array The first element represents the status, the second contains additional information
166+
*/
167+
protected function handleRouteRequirements($pathinfo, $name, Route $route)
168+
{
169+
// check HTTP scheme requirement
170+
$scheme = $route->getRequirement('_scheme');
171+
$status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
172+
173+
return array($status, null);
174+
}
175+
144176
protected function mergeDefaults($params, $defaults)
145177
{
146178
$parameters = $defaults;

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,13 @@ public function testMatchRegression()
207207
}
208208

209209
/**
210-
* @expectedException \LogicException
210+
* @expectedException Symfony\Component\Routing\Exception\ResourceNotFoundException
211211
*/
212212
public function testSchemeRequirement()
213213
{
214214
$coll = new RouteCollection();
215215
$coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https')));
216-
217216
$matcher = new UrlMatcher($coll, new RequestContext());
218217
$matcher->match('/foo');
219218
}
220-
}
219+
}

0 commit comments

Comments
 (0)