[HttpFoundation] fixed Request::create() method

When creating a Request with Request::create(), some information can
come from the URI and the server variable. Until now, it was not clear
which information had precedence over the other and as a matter of fact,
this method was not consistent.

Now, information contained in the URI always take precedence over
information coming from the server array. That makes sense as the server
array is often copied from another existing Request object.
This commit is contained in:
Fabien Potencier 2013-02-06 16:42:45 +01:00
parent 3446cb219a
commit bc4a0e751e
3 changed files with 58 additions and 19 deletions

View File

@ -4,6 +4,7 @@ CHANGELOG
2.2.0
-----
* fixed the Request::create() precedence (URI information always take precedence now)
* added Request::getTrustedProxies()
* deprecated Request::isProxyTrusted()
* [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects

View File

@ -253,6 +253,9 @@ class Request
/**
* Creates a Request based on a given URI and configuration.
*
* The information contained in the URI always take precedence
* over the other information (server and parameters).
*
* @param string $uri The URI
* @param string $method The HTTP method
* @param array $parameters The query (GET) or request (POST) parameters
@ -267,7 +270,7 @@ class Request
*/
public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
{
$defaults = array(
$server = array_replace(array(
'SERVER_NAME' => 'localhost',
'SERVER_PORT' => 80,
'HTTP_HOST' => 'localhost',
@ -280,32 +283,38 @@ class Request
'SCRIPT_FILENAME' => '',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'REQUEST_TIME' => time(),
);
), $server);
$server['PATH_INFO'] = '';
$server['REQUEST_METHOD'] = strtoupper($method);
$components = parse_url($uri);
if (isset($components['host'])) {
$defaults['SERVER_NAME'] = $components['host'];
$defaults['HTTP_HOST'] = $components['host'];
$server['SERVER_NAME'] = $components['host'];
$server['HTTP_HOST'] = $components['host'];
}
if (isset($components['scheme'])) {
if ('https' === $components['scheme']) {
$defaults['HTTPS'] = 'on';
$defaults['SERVER_PORT'] = 443;
$server['HTTPS'] = 'on';
$server['SERVER_PORT'] = 443;
} else {
unset($server['HTTPS']);
$server['SERVER_PORT'] = 80;
}
}
if (isset($components['port'])) {
$defaults['SERVER_PORT'] = $components['port'];
$defaults['HTTP_HOST'] = $defaults['HTTP_HOST'].':'.$components['port'];
$server['SERVER_PORT'] = $components['port'];
$server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port'];
}
if (isset($components['user'])) {
$defaults['PHP_AUTH_USER'] = $components['user'];
$server['PHP_AUTH_USER'] = $components['user'];
}
if (isset($components['pass'])) {
$defaults['PHP_AUTH_PW'] = $components['pass'];
$server['PHP_AUTH_PW'] = $components['pass'];
}
if (!isset($components['path'])) {
@ -316,7 +325,7 @@ class Request
case 'POST':
case 'PUT':
case 'DELETE':
$defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
$server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
case 'PATCH':
$request = $parameters;
$query = array();
@ -333,14 +342,8 @@ class Request
}
$queryString = http_build_query($query, '', '&');
$uri = $components['path'].('' !== $queryString ? '?'.$queryString : '');
$server = array_replace($defaults, $server, array(
'REQUEST_METHOD' => strtoupper($method),
'PATH_INFO' => '',
'REQUEST_URI' => $uri,
'QUERY_STRING' => $queryString,
));
$server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : '');
$server['QUERY_STRING'] = $queryString;
return new static($query, $request, array(), $cookies, $files, $server, $content);
}

View File

@ -222,6 +222,41 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($request->isSecure());
}
/**
* @covers Symfony\Component\HttpFoundation\Request::create
*/
public function testCreateCheckPrecedence()
{
// server is used by default
$request = Request::create('/', 'GET', array(), array(), array(), array(
'HTTP_HOST' => 'example.com',
'HTTPS' => 'on',
'SERVER_PORT' => 443,
'PHP_AUTH_USER' => 'fabien',
'PHP_AUTH_PW' => 'pa$$',
'QUERY_STRING' => 'foo=bar',
));
$this->assertEquals('example.com', $request->getHost());
$this->assertEquals(443, $request->getPort());
$this->assertTrue($request->isSecure());
$this->assertEquals('fabien', $request->getUser());
$this->assertEquals('pa$$', $request->getPassword());
$this->assertEquals('', $request->getQueryString());
// URI has precedence over server
$request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', array(), array(), array(), array(
'HTTP_HOST' => 'example.com',
'HTTPS' => 'on',
'SERVER_PORT' => 443,
));
$this->assertEquals('example.net', $request->getHost());
$this->assertEquals(8080, $request->getPort());
$this->assertFalse($request->isSecure());
$this->assertEquals('thomas', $request->getUser());
$this->assertEquals('pokemon', $request->getPassword());
$this->assertEquals('foo=bar', $request->getQueryString());
}
/**
* @covers Symfony\Component\HttpFoundation\Request::duplicate
*/