Upgrade to latest Symfony HttpFoundation tag. Closes #1865.

This commit is contained in:
Taylor Otwell
2013-05-01 14:19:10 -05:00
parent 92f602edbf
commit b9cf8dfb71
28 changed files with 1154 additions and 219 deletions

View File

@@ -30,10 +30,10 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface;
*/
class Request
{
const HEADER_CLIENT_IP = 'client_ip';
const HEADER_CLIENT_HOST = 'client_host';
const HEADER_CLIENT_IP = 'client_ip';
const HEADER_CLIENT_HOST = 'client_host';
const HEADER_CLIENT_PROTO = 'client_proto';
const HEADER_CLIENT_PORT = 'client_port';
const HEADER_CLIENT_PORT = 'client_port';
protected static $trustProxy = false;
@@ -53,6 +53,8 @@ class Request
self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT',
);
protected static $httpMethodParameterOverride = false;
/**
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
@@ -251,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
@@ -265,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',
@@ -278,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'])) {
@@ -314,7 +325,9 @@ class Request
case 'POST':
case 'PUT':
case 'DELETE':
$defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
if (!isset($server['CONTENT_TYPE'])) {
$server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
}
case 'PATCH':
$request = $parameters;
$query = array();
@@ -331,14 +344,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);
}
@@ -464,6 +471,8 @@ class Request
*/
public static function trustProxyData()
{
trigger_error('trustProxyData() is deprecated since version 2.0 and will be removed in 2.3. Use setTrustedProxies() instead.', E_USER_DEPRECATED);
self::$trustProxy = true;
}
@@ -482,6 +491,16 @@ class Request
self::$trustProxy = $proxies ? true : false;
}
/**
* Gets the list of trusted proxies.
*
* @return array An array of trusted proxies.
*/
public static function getTrustedProxies()
{
return self::$trustedProxies;
}
/**
* Sets the name for trusted headers.
*
@@ -496,6 +515,8 @@ class Request
*
* @param string $key The header key
* @param string $value The header name
*
* @throws \InvalidArgumentException
*/
public static function setTrustedHeaderName($key, $value)
{
@@ -511,6 +532,8 @@ class Request
* false otherwise.
*
* @return boolean
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3. Use getTrustedProxies instead.
*/
public static function isProxyTrusted()
{
@@ -560,6 +583,29 @@ class Request
return implode('&', $parts);
}
/**
* Enables support for the _method request parameter to determine the intended HTTP method.
*
* Be warned that enabling this feature might lead to CSRF issues in your code.
* Check that you are using CSRF tokens when required.
*
* The HTTP method can only be overridden when the real HTTP method is POST.
*/
public static function enableHttpMethodParameterOverride()
{
self::$httpMethodParameterOverride = true;
}
/**
* Checks whether support for the _method request parameter is enabled.
*
* @return Boolean True when the _method request parameter is enabled, false otherwise
*/
public static function getHttpMethodParameterOverride()
{
return self::$httpMethodParameterOverride;
}
/**
* Gets a "parameter" value.
*
@@ -657,8 +703,6 @@ class Request
*
* @see http://en.wikipedia.org/wiki/X-Forwarded-For
*
* @deprecated The proxy argument is deprecated since version 2.0 and will be removed in 2.3. Use setTrustedProxies instead.
*
* @api
*/
public function getClientIp()
@@ -703,7 +747,7 @@ class Request
*
* * http://localhost/mysite returns an empty string
* * http://localhost/mysite/about returns '/about'
* * htpp://localhost/mysite/enco%20ded returns '/enco%20ded'
* * http://localhost/mysite/enco%20ded returns '/enco%20ded'
* * http://localhost/mysite/about?var=1 returns '/about'
*
* @return string The raw path (i.e. not urldecoded)
@@ -897,8 +941,7 @@ class Request
*/
public function getUri()
{
$qs = $this->getQueryString();
if (null !== $qs) {
if (null !== $qs = $this->getQueryString()) {
$qs = '?'.$qs;
}
@@ -1017,26 +1060,51 @@ class Request
}
/**
* Gets the request method.
* Gets the request "intended" method.
*
* If the X-HTTP-Method-Override header is set, and if the method is a POST,
* then it is used to determine the "real" intended HTTP method.
*
* The _method request parameter can also be used to determine the HTTP method,
* but only if enableHttpMethodParameterOverride() has been called.
*
* The method is always an uppercased string.
*
* @return string The request method
*
* @api
*
* @see getRealMethod
*/
public function getMethod()
{
if (null === $this->method) {
$this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
if ('POST' === $this->method) {
$this->method = strtoupper($this->headers->get('X-HTTP-METHOD-OVERRIDE', $this->request->get('_method', $this->query->get('_method', 'POST'))));
if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
$this->method = strtoupper($method);
} elseif (self::$httpMethodParameterOverride) {
$this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
}
}
}
return $this->method;
}
/**
* Gets the "real" request method.
*
* @return string The request method
*
* @see getMethod
*/
public function getRealMethod()
{
return strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
}
/**
* Gets the mime type associated with the format.
*
@@ -1216,6 +1284,8 @@ class Request
* @param Boolean $asResource If true, a resource will be returned
*
* @return string|resource The request body content or a resource to read the body stream.
*
* @throws \LogicException
*/
public function getContent($asResource = false)
{
@@ -1275,7 +1345,18 @@ class Request
return $locales[0];
}
$preferredLanguages = array_values(array_intersect($preferredLanguages, $locales));
$extendedPreferredLanguages = array();
foreach ($preferredLanguages as $language) {
$extendedPreferredLanguages[] = $language;
if (false !== $position = strpos($language, '_')) {
$superLanguage = substr($language, 0, $position);
if (!in_array($superLanguage, $preferredLanguages)) {
$extendedPreferredLanguages[] = $superLanguage;
}
}
}
$preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales));
return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0];
}
@@ -1293,9 +1374,9 @@ class Request
return $this->languages;
}
$languages = $this->splitHttpAcceptHeader($this->headers->get('Accept-Language'));
$languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all();
$this->languages = array();
foreach ($languages as $lang => $q) {
foreach (array_keys($languages) as $lang) {
if (strstr($lang, '-')) {
$codes = explode('-', $lang);
if ($codes[0] == 'i') {
@@ -1335,7 +1416,7 @@ class Request
return $this->charsets;
}
return $this->charsets = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept-Charset')));
return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all());
}
/**
@@ -1351,14 +1432,15 @@ class Request
return $this->acceptableContentTypes;
}
return $this->acceptableContentTypes = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept')));
return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all());
}
/**
* Returns true if the request is a XMLHttpRequest.
*
* It works if your JavaScript library set an X-Requested-With HTTP header.
* It is known to work with Prototype, Mootools, jQuery.
* It is known to work with common JavaScript frameworks:
* @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
*
* @return Boolean true if the request is an XMLHttpRequest, false otherwise
*
@@ -1375,40 +1457,23 @@ class Request
* @param string $header Header to split
*
* @return array Array indexed by the values of the Accept-* header in preferred order
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3.
*/
public function splitHttpAcceptHeader($header)
{
if (!$header) {
return array();
}
trigger_error('splitHttpAcceptHeader() is deprecated since version 2.2 and will be removed in 2.3.', E_USER_DEPRECATED);
$values = array();
$groups = array();
foreach (array_filter(explode(',', $header)) as $value) {
// Cut off any q-value that might come after a semi-colon
if (preg_match('/;\s*(q=.*$)/', $value, $match)) {
$q = substr(trim($match[1]), 2);
$value = trim(substr($value, 0, -strlen($match[0])));
} else {
$q = 1;
$headers = array();
foreach (AcceptHeader::fromString($header)->all() as $item) {
$key = $item->getValue();
foreach ($item->getAttributes() as $name => $value) {
$key .= sprintf(';%s=%s', $name, $value);
}
$groups[$q][] = $value;
$headers[$key] = $item->getQuality();
}
krsort($groups);
foreach ($groups as $q => $items) {
$q = (float) $q;
if (0 < $q) {
foreach ($items as $value) {
$values[trim($value)] = $q;
}
}
}
return $values;
return $headers;
}
/*
@@ -1426,12 +1491,16 @@ class Request
if ($this->headers->has('X_ORIGINAL_URL') && false !== stripos(PHP_OS, 'WIN')) {
// IIS with Microsoft Rewrite Module
$requestUri = $this->headers->get('X_ORIGINAL_URL');
$this->headers->remove('X_ORIGINAL_URL');
} elseif ($this->headers->has('X_REWRITE_URL') && false !== stripos(PHP_OS, 'WIN')) {
// IIS with ISAPI_Rewrite
$requestUri = $this->headers->get('X_REWRITE_URL');
$this->headers->remove('X_REWRITE_URL');
} elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') {
// IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem)
$requestUri = $this->server->get('UNENCODED_URL');
$this->server->remove('UNENCODED_URL');
$this->server->remove('IIS_WasUrlRewritten');
} elseif ($this->server->has('REQUEST_URI')) {
$requestUri = $this->server->get('REQUEST_URI');
// HTTP proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path
@@ -1445,8 +1514,12 @@ class Request
if ('' != $this->server->get('QUERY_STRING')) {
$requestUri .= '?'.$this->server->get('QUERY_STRING');
}
$this->server->remove('ORIG_PATH_INFO');
}
// normalize the request URI to ease creating sub-requests from this request
$this->server->set('REQUEST_URI', $requestUri);
return $requestUri;
}