Permalink
Browse files

[HttpFoundation] disabled Request _method feature by default (should …

…now be explicitely enabled via a call to enableHttpMethodOverride())
  • Loading branch information...
1 parent 1b34ddb commit 0a380cfdbfe6233bd7ceafe1c179aacfdbf5b623 @fabpot fabpot committed Nov 28, 2012
View
3 UPGRADE-2.2.md
@@ -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
2 src/Symfony/Component/HttpFoundation/CHANGELOG.md
@@ -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
44 src/Symfony/Component/HttpFoundation/Request.php
@@ -32,6 +32,8 @@ class Request
{
protected static $trustProxy = false;
+ protected static $httpMethodParameterOverride = false;
+
/**
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
@@ -504,6 +506,19 @@ public static function normalizeQueryString($qs)
}
/**
+ * 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.
*
* This method is mainly useful for libraries that want to provide some flexibility.
@@ -915,27 +930,52 @@ 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');
@vicb
vicb Nov 28, 2012

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

@vicb
vicb Nov 28, 2012

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

@alvarezmario
alvarezmario Nov 28, 2012

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.
*
* @param string $format The format
View
28 src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
@@ -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');
@@ -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';
@@ -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()
@@ -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

0 comments on commit 0a380cf

Please sign in to comment.