Skip to content

Commit f5548f0

Browse files
committed
fix the edge case of double leading slash when rebuilding request
1 parent 9a59d98 commit f5548f0

File tree

3 files changed

+23
-32
lines changed

3 files changed

+23
-32
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Changelog
66

77
* **2016-01-09**: When ChainRouter::match is used with a RequestMatcher, the
88
Request is now properly rebuilt from the RequestContext if that was set on
9-
the ChainRouter.
9+
the ChainRouter, and http://localhost is used otherwise to avoid issues with
10+
paths starting with a double forward slash.
1011
* **2014-09-29**: ChainRouter does not require a RouterInterface, as a
1112
RequestMatcher and UrlGenerator is fine too. Fixed chain router interface to
1213
not force a RouterInterface.

ChainRouter.php

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ protected function sortRouters()
141141
*
142142
* Note: You should use matchRequest if you can.
143143
*/
144-
public function match($url)
144+
public function match($pathinfo)
145145
{
146-
return $this->doMatch($url);
146+
return $this->doMatch($pathinfo);
147147
}
148148

149149
/**
@@ -162,14 +162,14 @@ public function matchRequest(Request $request)
162162
* At least the url must be provided, if a request is additionally provided
163163
* the request takes precedence.
164164
*
165-
* @param string $url
165+
* @param string $pathinfo
166166
* @param Request $request
167167
*
168168
* @return array An array of parameters
169169
*
170170
* @throws ResourceNotFoundException If no router matched.
171171
*/
172-
private function doMatch($url, Request $request = null)
172+
private function doMatch($pathinfo, Request $request = null)
173173
{
174174
$methodNotAllowed = null;
175175

@@ -180,14 +180,14 @@ private function doMatch($url, Request $request = null)
180180
// matching requests is more powerful than matching URLs only, so try that first
181181
if ($router instanceof RequestMatcherInterface) {
182182
if (empty($requestForMatching)) {
183-
$requestForMatching = $this->rebuildRequest($url);
183+
$requestForMatching = $this->rebuildRequest($pathinfo);
184184
}
185185

186186
return $router->matchRequest($requestForMatching);
187187
}
188188

189189
// every router implements the match method
190-
return $router->match($url);
190+
return $router->match($pathinfo);
191191
} catch (ResourceNotFoundException $e) {
192192
if ($this->logger) {
193193
$this->logger->debug('Router '.get_class($router).' was not able to match, message "'.$e->getMessage().'"');
@@ -203,7 +203,7 @@ private function doMatch($url, Request $request = null)
203203

204204
$info = $request
205205
? "this request\n$request"
206-
: "url '$url'";
206+
: "url '$pathinfo'";
207207
throw $methodNotAllowed ?: new ResourceNotFoundException("None of the routers in the chain matched $info");
208208
}
209209

@@ -255,42 +255,32 @@ public function generate($name, $parameters = array(), $absolute = UrlGeneratorI
255255
*
256256
* If the request context is not set, this simply returns the request object built from $uri.
257257
*
258-
* @param string $uri
258+
* @param string $pathinfo
259259
*
260260
* @return Request
261261
*/
262-
private function rebuildRequest($uri)
262+
private function rebuildRequest($pathinfo)
263263
{
264264
if (!$this->context) {
265-
return Request::create($uri);
265+
return Request::create('http://localhost'.$pathinfo);
266266
}
267267

268+
$uri = $pathinfo;
269+
268270
$server = array();
269-
if ($this->context->getHost()) {
270-
$server['SERVER_NAME'] = $this->context->getHost();
271-
$server['HTTP_HOST'] = $this->context->getHost();
272-
}
273271
if ($this->context->getBaseUrl()) {
274-
$uri = $this->context->getBaseUrl().$uri;
272+
$uri = $this->context->getBaseUrl().$pathinfo;
275273
$server['SCRIPT_FILENAME'] = $this->context->getBaseUrl();
276274
$server['PHP_SELF'] = $this->context->getBaseUrl();
277275
}
278-
if ('https' === $this->context->getScheme()) {
279-
$server['HTTPS'] = 'on';
280-
$server['SERVER_PORT'] = $this->context->getHttpsPort();
281-
if (443 !== $this->context->getHttpsPort()) {
282-
// this is parsed from the host by symfony request
283-
// https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L971
284-
$server['HTTP_HOST'] .= ':'.$this->context->getHttpsPort();
285-
}
286-
} else {
287-
$server['SERVER_PORT'] = $this->context->getHttpPort();
288-
if (80 !== $this->context->getHttpPort()) {
289-
// this is parsed from the host by symfony request
290-
// https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L971
291-
$server['HTTP_HOST'] .= ':'.$this->context->getHttpPort();
292-
}
276+
$host = $this->context->getHost() ?: 'localhost';
277+
if ('https' === $this->context->getScheme() && 443 !== $this->context->getHttpsPort()) {
278+
$host .= ':'.$this->context->getHttpsPort();
279+
}
280+
if ('http' === $this->context->getScheme() && 80 !== $this->context->getHttpPort()) {
281+
$host .= ':'.$this->context->getHttpPort();
293282
}
283+
$uri = $this->context->getScheme().'://'.$host.$uri.$this->context->getQueryString();
294284

295285
return Request::create($uri, $this->context->getMethod(), $this->context->getParameters(), array(), array(), $server);
296286
}

Tests/Routing/ChainRouterTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ public function provideBaseUrl()
324324
*/
325325
public function testMatchWithRequestMatchersAndContext($baseUrl)
326326
{
327-
$url = '/test';
327+
$url = '//test';
328328

329329
list($low) = $this->createRouterMocks();
330330

0 commit comments

Comments
 (0)