Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 91ecd89

Browse filesBrowse files
committed
[Routing] support scheme requirement without redirectable dumped matcher
1 parent 308e12c commit 91ecd89
Copy full SHA for 91ecd89

22 files changed

+230
-222
lines changed

‎src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function testSchemeRedirect()
5353
'scheme' => 'https',
5454
'httpPort' => $context->getHttpPort(),
5555
'httpsPort' => $context->getHttpsPort(),
56-
'_route' => 'foo',
56+
'_route' => null,
5757
),
5858
$matcher->match('/foo')
5959
);

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php
+21-43Lines changed: 21 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ private function generateMatchMethod(): string
111111

112112
$code = <<<EOF
113113
{
114-
\$allow = array();
114+
\$allow = \$allowSchemes = array();
115115
\$pathinfo = rawurldecode(\$rawPathinfo);
116116
\$context = \$this->context;
117117
\$requestMethod = \$canonicalMethod = \$context->getMethod();
@@ -128,21 +128,26 @@ private function generateMatchMethod(): string
128128
return <<<'EOF'
129129
public function match($pathinfo)
130130
{
131-
$allow = array();
132-
if ($ret = $this->doMatch($pathinfo, $allow)) {
131+
$allow = $allowSchemes = array();
132+
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
133133
return $ret;
134134
}
135-
if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
136-
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
137-
if ($ret = $this->doMatch($pathinfo)) {
138-
return $this->redirect($pathinfo, $ret['_route']) + $ret;
135+
if (in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
136+
if ($allowSchemes) {
137+
return $this->redirect($pathinfo, null, key($allowSchemes));
138+
}
139+
if ('/' !== $pathinfo) {
140+
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
141+
if ($ret = $this->doMatch($pathinfo)) {
142+
return $this->redirect($pathinfo, $ret['_route']) + $ret;
143+
}
139144
}
140145
}
141146
142147
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
143148
}
144149
145-
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
150+
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
146151

147152
EOF
148153
.$code."\n return null;\n }";
@@ -238,9 +243,6 @@ private function compileStaticRoutes(array $staticRoutes, bool $matchHost): stri
238243
}
239244

240245
if (!$route->getCondition()) {
241-
if (!$this->supportsRedirections && $route->getSchemes()) {
242-
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
243-
}
244246
$default .= sprintf(
245247
"%s => array(%s, %s, %s, %s),\n",
246248
self::export($url),
@@ -535,8 +537,8 @@ private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
535537
} else {
536538
$code = '';
537539
}
538-
if ($this->supportsRedirections) {
539-
$code .= <<<EOF
540+
541+
$code .= <<<EOF
540542
541543
\$hasRequiredScheme = !\$requiredSchemes || isset(\$requiredSchemes[\$context->getScheme()]);
542544
if (\$requiredMethods && !isset(\$requiredMethods[\$canonicalMethod]) && !isset(\$requiredMethods[\$requestMethod])) {
@@ -545,29 +547,14 @@ private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
545547
}
546548
break;
547549
}
548-
if (!\$hasRequiredScheme) {
549-
if ('GET' !== \$canonicalMethod) {
550-
break;
551-
}
552-
553-
return \$this->redirect(\$rawPathinfo, \$ret['_route'], key(\$requiredSchemes)) + \$ret;
554-
}
555-
556-
return \$ret;
557-
558-
EOF;
559-
} else {
560-
$code .= <<<EOF
561-
562-
if (\$requiredMethods && !isset(\$requiredMethods[\$canonicalMethod]) && !isset(\$requiredMethods[\$requestMethod])) {
563-
\$allow += \$requiredMethods;
550+
if (\$requiredSchemes && !\$hasRequiredScheme) {
551+
\$allowSchemes += \$requiredSchemes;
564552
break;
565553
}
566554
567555
return \$ret;
568556
569557
EOF;
570-
}
571558

572559
return $code;
573560
}
@@ -647,9 +634,6 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
647634
}
648635

649636
if ($schemes = $route->getSchemes()) {
650-
if (!$this->supportsRedirections) {
651-
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
652-
}
653637
$schemes = self::export(array_flip($schemes));
654638
if ($methods) {
655639
$code .= <<<EOF
@@ -662,11 +646,8 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
662646
goto $gotoname;
663647
}
664648
if (!\$hasRequiredScheme) {
665-
if ('GET' !== \$canonicalMethod) {
666-
goto $gotoname;
667-
}
668-
669-
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)) + \$ret;
649+
\$allowSchemes += \$requiredSchemes;
650+
goto $gotoname;
670651
}
671652
672653
@@ -675,11 +656,8 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
675656
$code .= <<<EOF
676657
\$requiredSchemes = $schemes;
677658
if (!isset(\$requiredSchemes[\$context->getScheme()])) {
678-
if ('GET' !== \$canonicalMethod) {
679-
goto $gotoname;
680-
}
681-
682-
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)) + \$ret;
659+
\$allowSchemes += \$requiredSchemes;
660+
goto $gotoname;
683661
}
684662
685663

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php
+9-21Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@ public function match($pathinfo)
2727
try {
2828
return parent::match($pathinfo);
2929
} catch (ResourceNotFoundException $e) {
30-
if ('/' === $pathinfo || !\in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
30+
if (!\in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
31+
throw $e;
32+
}
33+
34+
if ($this->allowSchemes) {
35+
return $this->redirect($pathinfo, null, current($this->allowSchemes));
36+
}
37+
38+
if ('/' === $pathinfo) {
3139
throw $e;
3240
}
3341

@@ -41,24 +49,4 @@ public function match($pathinfo)
4149
}
4250
}
4351
}
44-
45-
/**
46-
* {@inheritdoc}
47-
*/
48-
protected function handleRouteRequirements($pathinfo, $name, Route $route)
49-
{
50-
// expression condition
51-
if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) {
52-
return array(self::REQUIREMENT_MISMATCH, null);
53-
}
54-
55-
// check HTTP scheme requirement
56-
$scheme = $this->context->getScheme();
57-
$schemes = $route->getSchemes();
58-
if ($schemes && !$route->hasScheme($scheme)) {
59-
return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, current($schemes)));
60-
}
61-
62-
return array(self::REQUIREMENT_MATCH, null);
63-
}
6452
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Matcher/UrlMatcher.php
+22-8Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,19 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
3333
const ROUTE_MATCH = 2;
3434

3535
protected $context;
36+
37+
/**
38+
* Collects HTTP methods that would be allowed for the request
39+
*/
3640
protected $allow = array();
41+
42+
/**
43+
* Collects URI schemes that would be allowed for the request
44+
*
45+
* @internal
46+
*/
47+
protected $allowSchemes = array();
48+
3749
protected $routes;
3850
protected $request;
3951
protected $expressionLanguage;
@@ -70,7 +82,7 @@ public function getContext()
7082
*/
7183
public function match($pathinfo)
7284
{
73-
$this->allow = array();
85+
$this->allow = $this->allowSchemes = array();
7486

7587
if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
7688
return $ret;
@@ -141,22 +153,28 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
141153
continue;
142154
}
143155

144-
// check HTTP method requirement
156+
$hasRequiredScheme = !$route->getSchemes() || $route->hasScheme($this->context->getScheme());
145157
if ($requiredMethods = $route->getMethods()) {
146158
// HEAD and GET are equivalent as per RFC
147159
if ('HEAD' === $method = $this->context->getMethod()) {
148160
$method = 'GET';
149161
}
150162

151163
if (!in_array($method, $requiredMethods)) {
152-
if (self::REQUIREMENT_MATCH === $status[0]) {
164+
if ($hasRequiredScheme) {
153165
$this->allow = array_merge($this->allow, $requiredMethods);
154166
}
155167

156168
continue;
157169
}
158170
}
159171

172+
if (!$hasRequiredScheme) {
173+
$this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes());
174+
175+
continue;
176+
}
177+
160178
return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : array()));
161179
}
162180
}
@@ -197,11 +215,7 @@ protected function handleRouteRequirements($pathinfo, $name, Route $route)
197215
return array(self::REQUIREMENT_MISMATCH, null);
198216
}
199217

200-
// check HTTP scheme requirement
201-
$scheme = $this->context->getScheme();
202-
$status = $route->getSchemes() && !$route->hasScheme($scheme) ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
203-
204-
return array($status, null);
218+
return array(self::REQUIREMENT_MATCH, null);
205219
}
206220

207221
/**

‎src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function __construct(RequestContext $context)
1717

1818
public function match($rawPathinfo)
1919
{
20-
$allow = array();
20+
$allow = $allowSchemes = array();
2121
$pathinfo = rawurldecode($rawPathinfo);
2222
$context = $this->context;
2323
$requestMethod = $canonicalMethod = $context->getMethod();

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php
+17-3Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function __construct(RequestContext $context)
1717

1818
public function match($rawPathinfo)
1919
{
20-
$allow = array();
20+
$allow = $allowSchemes = array();
2121
$pathinfo = rawurldecode($rawPathinfo);
2222
$context = $this->context;
2323
$requestMethod = $canonicalMethod = $context->getMethod();
@@ -64,8 +64,15 @@ public function match($rawPathinfo)
6464
}
6565
}
6666

67+
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
6768
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
68-
$allow += $requiredMethods;
69+
if ($hasRequiredScheme) {
70+
$allow += $requiredMethods;
71+
}
72+
break;
73+
}
74+
if ($requiredSchemes && !$hasRequiredScheme) {
75+
$allowSchemes += $requiredSchemes;
6976
break;
7077
}
7178

@@ -209,8 +216,15 @@ public function match($rawPathinfo)
209216
}
210217
}
211218

219+
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
212220
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
213-
$allow += $requiredMethods;
221+
if ($hasRequiredScheme) {
222+
$allow += $requiredMethods;
223+
}
224+
break;
225+
}
226+
if ($requiredSchemes && !$hasRequiredScheme) {
227+
$allowSchemes += $requiredSchemes;
214228
break;
215229
}
216230

‎src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php
+9-2Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function __construct(RequestContext $context)
1717

1818
public function match($rawPathinfo)
1919
{
20-
$allow = array();
20+
$allow = $allowSchemes = array();
2121
$pathinfo = rawurldecode($rawPathinfo);
2222
$context = $this->context;
2323
$requestMethod = $canonicalMethod = $context->getMethod();
@@ -2799,8 +2799,15 @@ public function match($rawPathinfo)
27992799
}
28002800
}
28012801

2802+
$hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]);
28022803
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
2803-
$allow += $requiredMethods;
2804+
if ($hasRequiredScheme) {
2805+
$allow += $requiredMethods;
2806+
}
2807+
break;
2808+
}
2809+
if ($requiredSchemes && !$hasRequiredScheme) {
2810+
$allowSchemes += $requiredSchemes;
28042811
break;
28052812
}
28062813

‎src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher11.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher11.php
+16-14Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,28 @@ public function __construct(RequestContext $context)
1717

1818
public function match($pathinfo)
1919
{
20-
$allow = array();
21-
if ($ret = $this->doMatch($pathinfo, $allow)) {
20+
$allow = $allowSchemes = array();
21+
if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) {
2222
return $ret;
2323
}
24-
if ('/' !== $pathinfo && in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
25-
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
26-
if ($ret = $this->doMatch($pathinfo)) {
27-
return $this->redirect($pathinfo, $ret['_route']) + $ret;
24+
if (in_array($this->context->getMethod(), array('HEAD', 'GET'), true)) {
25+
if ($allowSchemes) {
26+
return $this->redirect($pathinfo, null, key($allowSchemes));
27+
}
28+
if ('/' !== $pathinfo) {
29+
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
30+
if ($ret = $this->doMatch($pathinfo)) {
31+
return $this->redirect($pathinfo, $ret['_route']) + $ret;
32+
}
2833
}
2934
}
3035

3136
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
3237
}
3338

34-
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
39+
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
3540
{
36-
$allow = array();
41+
$allow = $allowSchemes = array();
3742
$pathinfo = rawurldecode($rawPathinfo);
3843
$context = $this->context;
3944
$requestMethod = $canonicalMethod = $context->getMethod();
@@ -112,12 +117,9 @@ private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
112117
}
113118
break;
114119
}
115-
if (!$hasRequiredScheme) {
116-
if ('GET' !== $canonicalMethod) {
117-
break;
118-
}
119-
120-
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
120+
if ($requiredSchemes && !$hasRequiredScheme) {
121+
$allowSchemes += $requiredSchemes;
122+
break;
121123
}
122124

123125
return $ret;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.