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 2bcc2a9

Browse filesBrowse files
committed
[Routing] support scheme requirement without redirectable dumped matcher
1 parent be1a3b4 commit 2bcc2a9
Copy full SHA for 2bcc2a9
Expand file treeCollapse file tree

22 files changed

+230
-221
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
+34-42Lines changed: 34 additions & 42 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,27 @@ 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+
140+
if ('/' !== $pathinfo) {
141+
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
142+
if ($ret = $this->doMatch($pathinfo)) {
143+
return $this->redirect($pathinfo, $ret['_route']) + $ret;
144+
}
139145
}
140146
}
141147
142148
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
143149
}
144150
145-
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
151+
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
146152

147153
EOF
148154
.$code."\n return null;\n }";
@@ -238,9 +244,6 @@ private function compileStaticRoutes(array $staticRoutes, bool $matchHost): stri
238244
}
239245

240246
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-
}
244247
$default .= sprintf(
245248
"%s => array(%s, %s, %s, %s),\n",
246249
self::export($url),
@@ -535,24 +538,20 @@ private function compileSwitchDefault(bool $hasVars, bool $matchHost): string
535538
} else {
536539
$code = '';
537540
}
538-
if ($this->supportsRedirections) {
539-
$code .= <<<EOF
540541

541-
if (\$requiredSchemes && !isset(\$requiredSchemes[\$context->getScheme()])) {
542-
if ('GET' !== \$canonicalMethod) {
543-
\$allow['GET'] = 'GET';
544-
break;
545-
}
542+
$code .= <<<EOF
546543
547-
return \$this->redirect(\$rawPathinfo, \$ret['_route'], key(\$requiredSchemes)) + \$ret;
544+
if (\$requiredMethods && !isset(\$requiredMethods[\$canonicalMethod]) && !isset(\$requiredMethods[\$requestMethod])) {
545+
\$allow += \$requiredMethods;
546+
break;
548547
}
549548
550549
EOF;
551-
}
550+
552551
$code .= <<<EOF
553552
554-
if (\$requiredMethods && !isset(\$requiredMethods[\$canonicalMethod]) && !isset(\$requiredMethods[\$requestMethod])) {
555-
\$allow += \$requiredMethods;
553+
if (\$requiredSchemes && !isset(\$requiredSchemes[\$context->getScheme()])) {
554+
\$allowSchemes += \$requiredSchemes;
556555
break;
557556
}
558557
@@ -575,7 +574,6 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
575574
$conditions = array();
576575
$matches = (bool) $compiledRoute->getPathVariables();
577576
$hostMatches = (bool) $compiledRoute->getHostVariables();
578-
$methods = array_flip($route->getMethods());
579577

580578
if ($route->getCondition()) {
581579
$expression = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request'));
@@ -632,33 +630,27 @@ private function compileRoute(Route $route, string $name, bool $checkHost): stri
632630
$code .= sprintf(" \$ret = array('_route' => '%s');\n", $name);
633631
}
634632

635-
if ($schemes = $route->getSchemes()) {
636-
if (!$this->supportsRedirections) {
637-
throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.');
638-
}
639-
$schemes = self::export(array_flip($schemes));
640-
$code .= <<<EOF
641-
\$requiredSchemes = $schemes;
642-
if (!isset(\$requiredSchemes[\$context->getScheme()])) {
643-
if ('GET' !== \$canonicalMethod) {
644-
\$allow['GET'] = 'GET';
645-
goto $gotoname;
646-
}
633+
if ($methods = $route->getMethods()) {
634+
$methods = array_flip($methods);
635+
$methodVariable = isset($methods['GET']) ? '$canonicalMethod' : '$requestMethod';
636+
$methods = self::export($methods);
647637

648-
return \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes)) + \$ret;
638+
$code .= <<<EOF
639+
if (!isset((\$a = {$methods})[{$methodVariable}])) {
640+
\$allow += \$a;
641+
goto $gotoname;
649642
}
650643
651644
652645
EOF;
653646
}
654647

655-
if ($methods) {
656-
$methodVariable = isset($methods['GET']) ? '$canonicalMethod' : '$requestMethod';
657-
$methods = self::export($methods);
658-
648+
if ($schemes = $route->getSchemes()) {
649+
$schemes = self::export(array_flip($schemes));
659650
$code .= <<<EOF
660-
if (!isset((\$a = {$methods})[{$methodVariable}])) {
661-
\$allow += \$a;
651+
\$requiredSchemes = $schemes;
652+
if (!isset(\$requiredSchemes[\$context->getScheme()])) {
653+
\$allowSchemes += \$requiredSchemes;
662654
goto $gotoname;
663655
}
664656

‎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-6Lines changed: 22 additions & 6 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;
@@ -149,12 +161,20 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
149161
}
150162
}
151163

164+
// check custom requirements
152165
$status = $this->handleRouteRequirements($pathinfo, $name, $route);
153166

154167
if (self::REQUIREMENT_MISMATCH === $status[0]) {
155168
continue;
156169
}
157170

171+
// check URI scheme requirement
172+
if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) {
173+
$this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes());
174+
175+
continue;
176+
}
177+
158178
return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : array()));
159179
}
160180
}
@@ -195,11 +215,7 @@ protected function handleRouteRequirements($pathinfo, $name, Route $route)
195215
return array(self::REQUIREMENT_MISMATCH, null);
196216
}
197217

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

205221
/**

‎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
+11-1Lines changed: 11 additions & 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();
@@ -69,6 +69,11 @@ public function match($rawPathinfo)
6969
break;
7070
}
7171

72+
if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) {
73+
$allowSchemes += $requiredSchemes;
74+
break;
75+
}
76+
7277
return $ret;
7378
}
7479

@@ -214,6 +219,11 @@ public function match($rawPathinfo)
214219
break;
215220
}
216221

222+
if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) {
223+
$allowSchemes += $requiredSchemes;
224+
break;
225+
}
226+
217227
return $ret;
218228
}
219229

‎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
+6-1Lines changed: 6 additions & 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();
@@ -2804,6 +2804,11 @@ public function match($rawPathinfo)
28042804
break;
28052805
}
28062806

2807+
if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) {
2808+
$allowSchemes += $requiredSchemes;
2809+
break;
2810+
}
2811+
28072812
return $ret;
28082813
}
28092814

‎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
+19-17Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,29 @@ 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+
29+
if ('/' !== $pathinfo) {
30+
$pathinfo = '/' !== $pathinfo[-1] ? $pathinfo.'/' : substr($pathinfo, 0, -1);
31+
if ($ret = $this->doMatch($pathinfo)) {
32+
return $this->redirect($pathinfo, $ret['_route']) + $ret;
33+
}
2834
}
2935
}
3036

3137
throw $allow ? new MethodNotAllowedException(array_keys($allow)) : new ResourceNotFoundException();
3238
}
3339

34-
private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
40+
private function doMatch(string $rawPathinfo, array &$allow = array(), array &$allowSchemes = array()): ?array
3541
{
36-
$allow = array();
42+
$allow = $allowSchemes = array();
3743
$pathinfo = rawurldecode($rawPathinfo);
3844
$context = $this->context;
3945
$requestMethod = $canonicalMethod = $context->getMethod();
@@ -105,20 +111,16 @@ private function doMatch(string $rawPathinfo, array &$allow = array()): ?array
105111
}
106112
}
107113

108-
if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) {
109-
if ('GET' !== $canonicalMethod) {
110-
$allow['GET'] = 'GET';
111-
break;
112-
}
113-
114-
return $this->redirect($rawPathinfo, $ret['_route'], key($requiredSchemes)) + $ret;
115-
}
116-
117114
if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) {
118115
$allow += $requiredMethods;
119116
break;
120117
}
121118

119+
if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) {
120+
$allowSchemes += $requiredSchemes;
121+
break;
122+
}
123+
122124
return $ret;
123125
}
124126

0 commit comments

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