8000 [Routing] Throw 405 instead of 404 when trailing slash redirection is… · symfony/symfony@828d6fe · GitHub
[go: up one dir, main page]

Skip to content

Commit 828d6fe

Browse files
[Routing] Throw 405 instead of 404 when trailing slash redirection is not possible
1 parent f7d9701 commit 828d6fe

File tree

4 files changed

+51
-25
lines changed

4 files changed

+51
-25
lines changed

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

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -258,34 +258,13 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
258258
EOF;
259259

260260
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
261-
if ($methods) {
262-
if (1 === count($methods)) {
263-
$code .= <<<EOF
264-
if (\$this->context->getMethod() != '$methods[0]') {
265-
\$allow[] = '$methods[0]';
266-
goto $gotoname;
267-
}
268-
269-
270-
EOF;
271-
} else {
272-
$methods = implode("', '", $methods);
273-
$code .= <<<EOF
274-
if (!in_array(\$this->context->getMethod(), array('$methods'))) {
275-
\$allow = array_merge(\$allow, array('$methods'));
276-
goto $gotoname;
277-
}
278-
279-
280-
EOF;
281-
}
282-
}
283261

284262
if ($hasTrailingSlash) {
285263
$code .= <<<EOF
286264
if ('/' === substr(\$pathinfo, -1)) {
287265
// no-op
288266
} elseif (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
267+
\$allow[] = 'GET';
289268
goto $gotoname;
290269
} else {
291270
return \$this->redirect(\$rawPathinfo.'/', '$name');
@@ -303,13 +282,41 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
303282
$code .= <<<EOF
304283
\$requiredSchemes = $schemes;
305284
if (!isset(\$requiredSchemes[\$this->context->getScheme()])) {
285+
if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
286+
\$allow[] = 'GET';
287+
goto $gotoname;
288+
}
289+
306290
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes));
307291
}
308292
309293
310294
EOF;
311295
}
312296

297+
if ($methods) {
298+
if (1 === count($methods)) {
299+
$code .= <<<EOF
300+
if (\$this->context->getMethod() != '$methods[0]') {
301+
\$allow[] = '$methods[0]';
302+
goto $gotoname;
303+
}
304+
305+
306+
EOF;
307+
} else {
308+
$methods = implode("', '", $methods);
309+
$code .= <<<EOF
310+
if (!in_array(\$this->context->getMethod(), array('$methods'))) {
311+
\$allow = array_merge(\$allow, array('$methods'));
312+
goto $gotoname;
313+
}
314+
315+
316+
EOF;
317+
}
318+
}
319+
313320
// optimize parameters array
314321
if ($matches || $hostMatches) {
315322
$vars = array();
@@ -333,7 +340,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
333340
}
334341
$code .= " }\n";
335342

336-
if ($methods || $hasTrailingSlash) {
343+
if ($hasTrailingSlash || $schemes || $methods) {
337344
$code .= " $gotoname:\n";
338345
}
339346

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Routing\Matcher;
1313

14+
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
1415
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
1516
use Symfony\Component\Routing\Route;
1617

@@ -27,9 +28,12 @@ public function match($pathinfo)
2728
try {
2829
$parameters = parent::match($pathinfo);
2930
} catch (ResourceNotFoundException $e) {
30-
if ('/' === substr($pathinfo, -1) || !in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
31+
if ('/' === substr($pathinfo, -1)) {
3132
throw $e;
3233
}
34+
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
35+
throw new MethodNotAllowedException(array('GET'));
36+
}
3337

3438
try {
3539
parent::match($pathinfo.'/');

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public function match($rawPathinfo)
6969
if ('/' === substr($pathinfo, -1)) {
7070
// no-op
7171
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
72+
$allow[] = 'GET';
7273
goto not_baz3;
7374
} else {
7475
return $this->redirect($rawPathinfo.'/', 'baz3');
@@ -85,6 +86,7 @@ public function match($rawPathinfo)
8586
if ('/' === substr($pathinfo, -1)) {
8687
// no-op
8788
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
89+
$allow[] = 'GET';
8890
goto not_baz4;
8991
} else {
9092
return $this->redirect($rawPathinfo.'/', 'baz4');
@@ -183,6 +185,7 @@ public function match($rawPathinfo)
183185
if ('/' === substr($pathinfo, -1)) {
184186
// no-op
185187
} elseif (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
188+
$allow[] = 'GET';
186189
goto not_hey;
187190
} else {
188191
return $this->redirect($rawPathinfo.'/', 'hey');
@@ -333,21 +336,33 @@ public function match($rawPathinfo)
333336
if ('/secure' === $pathinfo) {
334337
$requiredSchemes = array ( 'https' => 0,);
335338
if (!isset($requiredSchemes[$this->context->getScheme()])) {
339+
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
340+
$allow[] = 'GET';
341+
goto not_secure;
342+
}
343+
336344
return $this->redirect($rawPathinfo, 'secure', key($requiredSchemes));
337345
}
338346

339347
return array('_route' => 'secure');
340348
}
349+
not_secure:
341350

342351
// nonsecure
343352
if ('/nonsecure' === $pathinfo) {
344353
$requiredSchemes = array ( 'http' => 0,);
345354
if (!isset($requiredSchemes[$this->context->getScheme()])) {
355+
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
356+
$allow[] = 'GET';
357+
goto not_nonsecure;
358+
}
359+
346360
return $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes));
347361
}
348362

349363
return array('_route' => 'nonsecure');
350364
}
365+
not_nonsecure:
351366

352367
throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException();
353368
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public function testRedirectWhenNoSlash()
2828
}
2929

3030
/**
31-
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
31+
* @expectedException \Symfony\Component\Routing\Exception\MethodNotAllowedException
3232
*/
3333
public function testRedirectWhenNoSlashForNonSafeMethod()
3434
{

0 commit comments

Comments
 (0)
0