Skip to content

Commit c4a5dd5

Browse files
Merge branch '2.8' into 3.4
* 2.8: [Routing] Throw 405 instead of 404 when redirect is not possible [Process] fix test case Add security.tl.xlf to legacy directory [Security][Validator] Add translations for Tagalog fixed typo Typo fix in security component lithuanian translation. [Process] Check PHP_BINDIR before $PATH in PhpExecutableFinder
2 parents f505f18 + 39d54f5 commit c4a5dd5

File tree

8 files changed

+180
-120
lines changed

8 files changed

+180
-120
lines changed

Matcher/Dumper/PhpMatcherDumper.php

Lines changed: 62 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
237237
$hostMatches = false;
238238
$methods = $route->getMethods();
239239

240-
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods) || in_array('GET', $methods));
240+
$supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('GET', $methods));
241241
$regex = $compiledRoute->getRegex();
242242

243243
if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#'.('u' === substr($regex, -1) ? 'u' : ''), $regex, $m)) {
@@ -279,59 +279,6 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
279279

280280
$gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name);
281281

282-
if ($methods) {
283-
if (1 === count($methods)) {
284-
if ('HEAD' === $methods[0]) {
285-
$code .= <<<EOF
286-
if ('HEAD' !== \$requestMethod) {
287-
\$allow[] = 'HEAD';
288-
goto $gotoname;
289-
}
290-
291-
292-
EOF;
293-
} else {
294-
$code .= <<<EOF
295-
if ('$methods[0]' !== \$canonicalMethod) {
296-
\$allow[] = '$methods[0]';
297-
goto $gotoname;
298-
}
299-
300-
301-
EOF;
302-
}
303-
} else {
304-
$methodVariable = 'requestMethod';
305-
306-
if (in_array('GET', $methods)) {
307-
// Since we treat HEAD requests like GET requests we don't need to match it.
308-
$methodVariable = 'canonicalMethod';
309-
$methods = array_values(array_filter($methods, function ($method) { return 'HEAD' !== $method; }));
310-
}
311-
312-
if (1 === count($methods)) {
313-
$code .= <<<EOF
314-
if ('$methods[0]' !== \$$methodVariable) {
315-
\$allow[] = '$methods[0]';
316-
goto $gotoname;
317-
}
318-
319-
320-
EOF;
321-
} else {
322-
$methods = implode("', '", $methods);
323-
$code .= <<<EOF
324-
if (!in_array(\$$methodVariable, array('$methods'))) {
325-
\$allow = array_merge(\$allow, array('$methods'));
326-
goto $gotoname;
327-
}
328-
329-
330-
EOF;
331-
}
332-
}
333-
}
334-
335282
// the offset where the return value is appended below, with indendation
336283
$retOffset = 12 + strlen($code);
337284

@@ -362,6 +309,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
362309
if ('/' === substr(\$pathinfo, -1)) {
363310
// no-op
364311
} elseif ('GET' !== \$canonicalMethod) {
312+
\$allow[] = 'GET';
365313
goto $gotoname;
366314
} else {
367315
return array_replace(\$ret, \$this->redirect(\$rawPathinfo.'/', '$name'));
@@ -379,21 +327,79 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren
379327
$code .= <<<EOF
380328
\$requiredSchemes = $schemes;
381329
if (!isset(\$requiredSchemes[\$context->getScheme()])) {
330+
if (!in_array(\$this->context->getMethod(), array('HEAD', 'GET'))) {
331+
\$allow[] = 'GET';
332+
goto $gotoname;
333+
}
334+
382335
return array_replace(\$ret, \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)));
383336
}
384337
385338
386339
EOF;
387340
}
388341

389-
if ($hasTrailingSlash || $schemes) {
342+
if ($methods) {
343+
if (1 === count($methods)) {
344+
if ('HEAD' === $methods[0]) {
345+
$code .= <<<EOF
346+
if ('HEAD' !== \$requestMethod) {
347+
\$allow[] = 'HEAD';
348+
goto $gotoname;
349+
}
350+
351+
352+
EOF;
353+
} else {
354+
$code .= <<<EOF
355+
if ('$methods[0]' !== \$canonicalMethod) {
356+
\$allow[] = '$methods[0]';
357+
goto $gotoname;
358+
}
359+
360+
361+
EOF;
362+
}
363+
} else {
364+
$methodVariable = 'requestMethod';
365+
366+
if (in_array('GET', $methods)) {
367+
// Since we treat HEAD requests like GET requests we don't need to match it.
368+
$methodVariable = 'canonicalMethod';
369+
$methods = array_values(array_filter($methods, function ($method) { return 'HEAD' !== $method; }));
370+
}
371+
372+
if (1 === count($methods)) {
373+
$code .= <<<EOF
374+
if ('$methods[0]' !== \$$methodVariable) {
375+
\$allow[] = '$methods[0]';
376+
goto $gotoname;
377+
}
378+
379+
380+
EOF;
381+
} else {
382+
$methods = implode("', '", $methods);
383+
$code .= <<<EOF
384+
if (!in_array(\$$methodVariable, array('$methods'))) {
385+
\$allow = array_merge(\$allow, array('$methods'));
386+
goto $gotoname;
387+
}
388+
389+
390+
EOF;
391+
}
392+
}
393+
}
394+
395+
if ($hasTrailingSlash || $schemes || $methods) {
390396
$code .= " return \$ret;\n";
391397
} else {
392398
$code = substr_replace($code, 'return', $retOffset, 6);
393399
}
394400
$code .= " }\n";
395401

396-
if ($methods || $hasTrailingSlash) {
402+
if ($hasTrailingSlash || $schemes || $methods) {
397403
$code .= " $gotoname:\n";
398404
}
399405

Tests/Fixtures/dumper/url_matcher1.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,25 @@ public function match($rawPathinfo)
4444
elseif (0 === strpos($pathinfo, '/bar')) {
4545
// bar
4646
if (preg_match('#^/bar/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
47+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
4748
if ('GET' !== $canonicalMethod) {
4849
$allow[] = 'GET';
4950
goto not_bar;
5051
}
5152

52-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
53+
return $ret;
5354
}
5455
not_bar:
5556

5657
// barhead
5758
if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
59+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
5860
if ('GET' !== $canonicalMethod) {
5961
$allow[] = 'GET';
6062
goto not_barhead;
6163
}
6264

63-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
65+
return $ret;
6466
}
6567
not_barhead:
6668

@@ -92,23 +94,25 @@ public function match($rawPathinfo)
9294

9395
// baz5
9496
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
97+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
9598
if ('POST' !== $canonicalMethod) {
9699
$allow[] = 'POST';
97100
goto not_baz5;
98101
}
99102

100-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
103+
return $ret;
101104
}
102105
not_baz5:
103106

104107
// baz.baz6
105108
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
109+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
106110
if ('PUT' !== $canonicalMethod) {
107111
$allow[] = 'PUT';
108112
goto not_bazbaz6;
109113
}
110114

111-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
115+
return $ret;
112116
}
113117
not_bazbaz6:
114118

Tests/Fixtures/dumper/url_matcher2.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,25 @@ public function match($rawPathinfo)
4444
elseif (0 === strpos($pathinfo, '/bar')) {
4545
// bar
4646
if (preg_match('#^/bar/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
47+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
4748
if ('GET' !== $canonicalMethod) {
4849
$allow[] = 'GET';
4950
goto not_bar;
5051
}
5152

52-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ());
53+
return $ret;
5354
}
5455
not_bar:
5556

5657
// barhead
5758
if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#sD', $pathinfo, $matches)) {
59+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
5860
if ('GET' !== $canonicalMethod) {
5961
$allow[] = 'GET';
6062
goto not_barhead;
6163
}
6264

63-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ());
65+
return $ret;
6466
}
6567
not_barhead:
6668

@@ -84,6 +86,7 @@ public function match($rawPathinfo)
8486
if ('/' === substr($pathinfo, -1)) {
8587
// no-op
8688
} elseif ('GET' !== $canonicalMethod) {
89+
$allow[] = 'GET';
8790
goto not_baz3;
8891
} else {
8992
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz3'));
@@ -101,6 +104,7 @@ public function match($rawPathinfo)
101104
if ('/' === substr($pathinfo, -1)) {
102105
// no-op
103106
} elseif ('GET' !== $canonicalMethod) {
107+
$allow[] = 'GET';
104108
goto not_baz4;
105109
} else {
106110
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz4'));
@@ -112,23 +116,25 @@ public function match($rawPathinfo)
112116

113117
// baz5
114118
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
119+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
115120
if ('POST' !== $canonicalMethod) {
116121
$allow[] = 'POST';
117122
goto not_baz5;
118123
}
119124

120-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ());
125+
return $ret;
121126
}
122127
not_baz5:
123128

124129
// baz.baz6
125130
if (preg_match('#^/test/(?P<foo>[^/]++)/$#sD', $pathinfo, $matches)) {
131+
$ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
126132
if ('PUT' !== $canonicalMethod) {
127133
$allow[] = 'PUT';
128134
goto not_bazbaz6;
129135
}
130136

131-
return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ());
137+
return $ret;
132138
}
133139
not_bazbaz6:
134140

@@ -190,6 +196,7 @@ public function match($rawPathinfo)
190196
if ('/' === substr($pathinfo, -1)) {
191197
// no-op
192198
} elseif ('GET' !== $canonicalMethod) {
199+
$allow[] = 'GET';
193200
goto not_hey;
194201
} else {
195202
return array_replace($ret, $this->redirect($rawPathinfo.'/', 'hey'));
@@ -340,22 +347,34 @@ public function match($rawPathinfo)
340347
$ret = array('_route' => 'secure');
341348
$requiredSchemes = array ( 'https' => 0,);
342349
if (!isset($requiredSchemes[$context->getScheme()])) {
350+
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
351+
$allow[] = 'GET';
352+
goto not_secure;
353+
}
354+
343355
return array_replace($ret, $this->redirect($rawPathinfo, 'secure', key($requiredSchemes)));
344356
}
345357

346358
return $ret;
347359
}
360+
not_secure:
348361

349362
// nonsecure
350363
if ('/nonsecure' === $pathinfo) {
351364
$ret = array('_route' => 'nonsecure');
352365
$requiredSchemes = array ( 'http' => 0,);
353366
if (!isset($requiredSchemes[$context->getScheme()])) {
367+
if (!in_array($this->context->getMethod(), array('HEAD', 'GET'))) {
368+
$allow[] = 'GET';
369+
goto not_nonsecure;
370+
}
371+
354372
return array_replace($ret, $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes)));
355373
}
356374

357375
return $ret;
358376
}
377+
not_nonsecure:
359378

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

0 commit comments

Comments
 (0)