Skip to content

Commit 19e4acc

Browse files
[Routing] fix taking verb into account when redirecting
1 parent 86eb1a5 commit 19e4acc

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

Matcher/UrlMatcher.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,15 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
123123
foreach ($routes as $name => $route) {
124124
$compiledRoute = $route->compile();
125125
$staticPrefix = $compiledRoute->getStaticPrefix();
126+
$requiredMethods = $route->getMethods();
126127

127128
// check the static prefix of the URL first. Only use the more expensive preg_match when it matches
128129
if ('' === $staticPrefix || 0 === strpos($pathinfo, $staticPrefix)) {
129130
// no-op
130-
} elseif (!$supportsTrailingSlash) {
131+
} elseif (!$supportsTrailingSlash || ($requiredMethods && !\in_array('GET', $requiredMethods))) {
131132
continue;
132133
} elseif ('/' === substr($staticPrefix, -1) && substr($staticPrefix, 0, -1) === $pathinfo) {
133-
return;
134+
return $this->allow = array();
134135
} else {
135136
continue;
136137
}
@@ -148,7 +149,10 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
148149
}
149150

150151
if ($hasTrailingSlash && '/' !== substr($pathinfo, -1)) {
151-
return;
152+
if (!$requiredMethods || \in_array('GET', $requiredMethods)) {
153+
return $this->allow = array();
154+
}
155+
continue;
152156
}
153157

154158
$hostMatches = array();
@@ -163,7 +167,7 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
163167
}
164168

165169
// check HTTP method requirement
166-
if ($requiredMethods = $route->getMethods()) {
170+
if ($requiredMethods) {
167171
// HEAD and GET are equivalent as per RFC
168172
if ('HEAD' === $method = $this->context->getMethod()) {
169173
$method = 'GET';
@@ -180,6 +184,8 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
180184

181185
return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : array()));
182186
}
187+
188+
return array();
183189
}
184190

185191
/**

Tests/Matcher/RedirectableUrlMatcherTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,23 @@ public function testFallbackPage()
128128
$this->assertSame(array('_route' => 'foo'), $matcher->match('/foo'));
129129
}
130130

131+
public function testSlashAndVerbPrecedenceWithRedirection()
132+
{
133+
$coll = new RouteCollection();
134+
$coll->add('a', new Route('/api/customers/{customerId}/contactpersons', array(), array(), array(), '', array(), array('post')));
135+
$coll->add('b', new Route('/api/customers/{customerId}/contactpersons/', array(), array(), array(), '', array(), array('get')));
136+
137+
$matcher = $this->getUrlMatcher($coll);
138+
$expected = array(
139+
'_route' => 'b',
140+
'customerId' => '123',
141+
);
142+
$this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons/'));
143+
144+
$matcher->expects($this->once())->method('redirect')->with('/api/customers/123/contactpersons/')->willReturn(array());
145+
$this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons'));
146+
}
147+
131148
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
132149
{
133150
return $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($routes, $context ?: new RequestContext()));

Tests/Matcher/UrlMatcherTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,20 @@ public function testSchemeAndMethodMismatch()
502502
$matcher->match('/');
503503
}
504504

505+
public function testSlashAndVerbPrecedence()
506+
{
507+
$coll = new RouteCollection();
508+
$coll->add('a', new Route('/api/customers/{customerId}/contactpersons/', array(), array(), array(), '', array(), array('post')));
509+
$coll->add('b', new Route('/api/customers/{customerId}/contactpersons', array(), array(), array(), '', array(), array('get')));
510+
511+
$matcher = $this->getUrlMatcher($coll);
512+
$expected = array(
513+
'_route' => 'b',
514+
'customerId' => '123',
515+
);
516+
$this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons'));
517+
}
518+
505519
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
506520
{
507521
return new UrlMatcher($routes, $context ?: new RequestContext());

0 commit comments

Comments
 (0)