[HttpFoundation] disabled Request _method feature by default (should now be explicitely enabled via a call to enableHttpMethodOverride())

This commit is contained in:
Fabien Potencier 2012-11-28 10:31:19 +01:00
parent 1b34ddb6b4
commit 0a380cfdbf
4 changed files with 76 additions and 5 deletions

View File

@ -12,6 +12,9 @@
* The Stopwatch functionality was moved from HttpKernel\Debug to its own component
* The _method request parameter support has been disabled by default (call
Request::enableHttpMethodParameterOverride() to enable it).
#### Deprecations
* The `Request::splitHttpAcceptHeader()` is deprecated and will be removed in 2.3.

View File

@ -4,6 +4,8 @@ CHANGELOG
2.2.0
-----
* added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method)
* disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to enable it)
* Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3
2.1.0

View File

@ -32,6 +32,8 @@ class Request
{
protected static $trustProxy = false;
protected static $httpMethodParameterOverride = false;
/**
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
@ -503,6 +505,19 @@ 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 overriden when the real HTTP method is POST.
*/
public static function enableHttpMethodParameterOverride()
{
self::$httpMethodParameterOverride = true;
}
/**
* Gets a "parameter" value.
*
@ -915,26 +930,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 $this->server->get('REQUEST_METHOD', 'GET');
}
/**
* Gets the mime type associated with the format.
*

View File

@ -675,13 +675,28 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$request->setMethod('POST');
$request->request->set('_method', 'purge');
$this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
$this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');
$request = new Request();
$request->setMethod('POST');
$request->request->remove('_method');
$request->query->set('_method', 'purge');
$request->request->set('_method', 'purge');
Request::enableHttpMethodParameterOverride();
$this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
$this->disableHttpMethodParameterOverride();
$request = new Request();
$request->setMethod('POST');
$request->query->set('_method', 'purge');
$this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');
$request = new Request();
$request->setMethod('POST');
$request->query->set('_method', 'purge');
Request::enableHttpMethodParameterOverride();
$this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
$this->disableHttpMethodParameterOverride();
$request = new Request();
$request->setMethod('POST');
$request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
$this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST');
@ -807,6 +822,8 @@ class RequestTest extends \PHPUnit_Framework_TestCase
unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']);
$request = Request::createFromGlobals();
Request::enableHttpMethodParameterOverride();
$_POST['_method'] = $method;
$_POST['foo6'] = 'bar6';
$_SERVER['REQUEST_METHOD'] = 'POST';
@ -815,6 +832,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('bar6', $request->request->get('foo6'));
unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']);
$this->disableHttpMethodParameterOverride();
}
public function testOverrideGlobals()
@ -1254,6 +1272,14 @@ class RequestTest extends \PHPUnit_Framework_TestCase
$property->setAccessible(true);
$property->setValue(false);
}
private function disableHttpMethodParameterOverride()
{
$class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request');
$property = $class->getProperty('httpMethodParameterOverride');
$property->setAccessible(true);
$property->setValue(false);
}
}
class RequestContentProxy extends Request