Skip to content

Commit

Permalink
[HttpFoundation] disabled Request _method feature by default (should …
Browse files Browse the repository at this point in the history
…now be explicitely enabled via a call to enableHttpMethodOverride())
  • Loading branch information
fabpot committed Nov 28, 2012
1 parent 1b34ddb commit 0a380cf
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 3 deletions.
3 changes: 3 additions & 0 deletions UPGRADE-2.2.md
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Component/HttpFoundation/CHANGELOG.md
Expand Up @@ -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
Expand Down
44 changes: 42 additions & 2 deletions src/Symfony/Component/HttpFoundation/Request.php
Expand Up @@ -32,6 +32,8 @@ class Request
{
protected static $trustProxy = false;

protected static $httpMethodParameterOverride = false;

/**
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
Expand Down Expand Up @@ -503,6 +505,19 @@ public static function normalizeQueryString($qs)
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.
*
Expand Down Expand Up @@ -915,26 +930,51 @@ public function setMethod($method)
}

/**
* 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');

This comment has been minimized.

Copy link
@vicb

vicb Nov 28, 2012

Contributor

should probably be strtoupper($this->server->get('REQUEST_METHOD', 'GET'));

This comment has been minimized.

Copy link
@vicb

vicb Nov 28, 2012

Contributor

would "Original" be better than "Real" (any native speaker pov) ?

This comment has been minimized.

Copy link
@alvarezmario

alvarezmario Nov 28, 2012

Contributor

Indeed, "Original" sounds better. The UploadedFile class also has an originalName, not a realName. Maybe not to the point, but I think it's related.

}

/**
* Gets the mime type associated with the format.
*
Expand Down
28 changes: 27 additions & 1 deletion src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
Expand Up @@ -675,13 +675,28 @@ public function testGetSetMethod()

$request->setMethod('POST');
$request->request->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->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->request->remove('_method');
$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');
Expand Down Expand Up @@ -807,6 +822,8 @@ public function testCreateFromGlobals($method)

unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']);

$request = Request::createFromGlobals();
Request::enableHttpMethodParameterOverride();
$_POST['_method'] = $method;
$_POST['foo6'] = 'bar6';
$_SERVER['REQUEST_METHOD'] = 'POST';
Expand All @@ -815,6 +832,7 @@ public function testCreateFromGlobals($method)
$this->assertEquals('bar6', $request->request->get('foo6'));

unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']);
$this->disableHttpMethodParameterOverride();
}

public function testOverrideGlobals()
Expand Down Expand Up @@ -1254,6 +1272,14 @@ private function stopTrustingProxyData()
$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
Expand Down

0 comments on commit 0a380cf

Please sign in to comment.