8000 [Routing] Don't throw 405 when scheme requirement doesn't match · symfony/symfony@9d70ef0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9d70ef0

Browse files
[Routing] Don't throw 405 when scheme requirement doesn't match
1 parent d8395f5 commit 9d70ef0

File tree

4 files changed

+55
-11
lines changed

4 files changed

+55
-11
lines changed

src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,18 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
278278
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
279279
}
280280
$schemes = str_replace("\n", '', var_export(array_flip($schemes), true));
281-
$code .= <<<EOF
281+
if ($methods) {
282+
$methods = implode("', '", $methods);
283+
$code .= <<<EOF
282284
\$requiredSchemes = $schemes;
283-
if (!isset(\$requiredSchemes[\$this->context->getScheme()])) {
285+
\$hasRequiredScheme = isset(\$requiredSchemes[\$this->context->getScheme()]);
286+
if (!in_array(\$this->context->getMethod(), array('$methods'))) {
287+
if (\$hasRequiredScheme) {
288+
\$allow = array_merge(\$allow, array('$methods'));
289+
}
290+
goto $gotoname;
291+
}
292+
if (!\$hasRequiredScheme) {
284293
if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
285294
goto $gotoname;
286295
}
@@ -290,9 +299,21 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
290299
291300
292301
EOF;
293-
}
302+
} else {
303+
$code .= <<<EOF
304+
\$requiredSchemes = $schemes;
305+
if (!isset(\$requiredSchemes[\$this->context->getScheme()])) {
306+
if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
307+
goto $gotoname;
308+
}
294309
295-
if ($methods) {
310+
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes));
311+
}
312+
313+
314+
EOF;
315+
}
316+
} elseif ($methods) {
296317
if (1 === count($methods)) {
297318
$code .= <<<EOF
298319
if (\$this->context->getMethod() != '$methods[0]') {

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
129129
continue;
130130
}
131131

132+
$status = $this->handleRouteRequirements($pathinfo, $name, $route);
133+
134+
if (self::REQUIREMENT_MISMATCH === $status[0]) {
135+
continue;
136+
}
137+
132138
// check HTTP method requirement
133139
if ($requiredMethods = $route->getMethods()) {
134140
// HEAD and GET are equivalent as per RFC
@@ -137,22 +143,18 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
137143
}
138144

139145
if (!in_array($method, $requiredMethods)) {
140-
$this->allow = array_merge($this->allow, $requiredMethods);
146+
if (self::REQUIREMENT_MATCH === $status[0]) {
147+
$this->allow = array_merge($this->allow, $requiredMethods);
148+
}
141149

142150
continue;
143151
}
144152
}
145153

146-
$status = $this->handleRouteRequirements($pathinfo, $name, $route);
147-
148154
if (self::ROUTE_MATCH === $status[0]) {
149155
return $status[1];
150156
}
151157

152-
if (self::REQUIREMENT_MISMATCH === $status[0]) {
153-
continue;
154-
}
155-
156158
return $this->getAttributes($route, $name, array_replace($matches, $hostMatches));
157159
}
158160
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ public function testSchemeRequirement()
2626
parent::testSchemeRequirement();
2727
}
2828

29+
/**
30+
* @expectedException \LogicException
31+
* @expectedExceptionMessage The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.
32+
*/
33+
public function testSchemeAndMethodMismatch()
34+
{
35+
parent::testSchemeRequirement();
36+
}
37+
2938
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
3039
{
3140
static $i = 0;

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,18 @@ public function testNestedCollections()
464464
$this->assertEquals(array('_route' => 'buz'), $matcher->match('/prefix/buz'));
465465
}
466466

467+
/**
468+
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
469+
*/
470+
public function testSchemeAndMethodMismatch()
471+
{
472+
$coll = new RouteCollection();
473+
$coll->add('foo', new Route('/', array(), array(), array(), null, array('https'), array('POST')));
474+
475+
$matcher = $this->getUrlMatcher($coll);
476+
$matcher->match('/');
477+
}
478+
467479
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
468480
{
469481
return new UrlMatcher($routes, $context ?: new RequestContext());

0 commit comments

Comments
 (0)
0