Browse Source

`yii\web\Request::getBodyParams()` now generates 415 'Unsupported Media Type' error on invalid or missing 'Content-Type' header

tags/3.0.0-alpha1
Klimov Paul 7 years ago
parent
commit
e7943971d2
  1. 1
      framework/CHANGELOG.md
  2. 17
      framework/web/Request.php
  3. 4
      tests/framework/rest/UrlRuleTest.php
  4. 28
      tests/framework/web/RequestTest.php
  5. 4
      tests/framework/web/UrlRuleTest.php

1
framework/CHANGELOG.md

@ -8,6 +8,7 @@ Yii Framework 2 Change Log
- Bug #14458: Fixed `yii\filters\VerbFilter` uses case-insensitive comparison for the HTTP method name (klimov-paul)
- Enh #879: Caching implementation refactored according to PSR-16 'Simple Cache' specification (klimov-paul)
- Enh #11328: Added support for PSR-7 'HTTP Message' (klimov-paul)
- Enh #14522: `yii\web\Request::getBodyParams()` now generates 415 'Unsupported Media Type' error on invalid or missing 'Content-Type' header (klimov-paul)
- Enh #13799: CAPTCHA rendering logic extracted into `yii\captcha\DriverInterface`, which instance is available via `yii\captcha\CaptchaAction::$driver` field (vladis84, klimov-paul)
- Enh #9260: Mail view rendering encapsulated into `yii\mail\Template` class allowing rendering in isolation and access to `yii\mail\MessageInterface` instance via `$this->context->message` inside the view (klimov-paul)
- Enh #11058: Add `$checkAjax` parameter to method `yii\web\Controller::redirect()` which controls redirection in AJAX and PJAX requests (ivanovyordan)

17
framework/web/Request.php

@ -509,7 +509,8 @@ class Request extends \yii\base\Request implements RequestInterface
* If no parsers are configured for the current [[contentType]] it uses the PHP function `mb_parse_str()`
* to parse the [[rawBody|request body]].
* @return array the request parameters given in the request body.
* @throws \yii\base\InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]].
* @throws InvalidConfigException if a registered parser does not implement the [[RequestParserInterface]].
* @throws UnsupportedMediaTypeHttpException if unable to parse raw body.
* @see getMethod()
* @see getBodyParam()
* @see setBodyParams()
@ -523,12 +524,10 @@ class Request extends \yii\base\Request implements RequestInterface
return $this->_bodyParams;
}
$rawContentType = $this->getContentType();
if (($pos = strpos($rawContentType, ';')) !== false) {
$contentType = $this->getContentType();
if (($pos = strpos($contentType, ';')) !== false) {
// e.g. text/html; charset=UTF-8
$contentType = substr($rawContentType, 0, $pos);
} else {
$contentType = $rawContentType;
$contentType = trim(substr($contentType, 0, $pos));
}
if (isset($this->parsers[$contentType])) {
@ -544,9 +543,15 @@ class Request extends \yii\base\Request implements RequestInterface
}
$this->_bodyParams = $parser->parse($this);
} elseif ($this->getMethod() === 'POST') {
if ($contentType !== 'application/x-www-form-urlencoded' && $contentType !== 'multipart/form-data') {
throw new UnsupportedMediaTypeHttpException();
}
// PHP has already parsed the body so we have all params in $_POST
$this->_bodyParams = $_POST;
} else {
if ($contentType !== 'application/x-www-form-urlencoded') {
throw new UnsupportedMediaTypeHttpException();
}
$this->_bodyParams = [];
mb_parse_str($this->getRawBody(), $this->_bodyParams);
}

4
tests/framework/rest/UrlRuleTest.php

@ -363,7 +363,7 @@ class UrlRuleTest extends TestCase
}
/**
* @dataProvider testGetCreateUrlStatusProvider
* @dataProvider dataProviderGetCreateUrlStatus
* @param array $config
* @param array $tests
*/
@ -400,7 +400,7 @@ class UrlRuleTest extends TestCase
* - second element is the expected URL
* - third element is the expected result of getCreateUrlStatus() method
*/
public function testGetCreateUrlStatusProvider()
public function dataProviderGetCreateUrlStatus()
{
return [
'single controller' => [

28
tests/framework/web/RequestTest.php

@ -7,7 +7,9 @@
namespace yiiunit\framework\web;
use yii\http\MemoryStream;
use yii\web\Request;
use yii\web\UnsupportedMediaTypeHttpException;
use yiiunit\TestCase;
/**
@ -84,6 +86,7 @@ class RequestTest extends TestCase
$this->mockWebApplication();
$request = new Request();
$request->setHeader('Content-Type', 'application/x-www-form-urlencoded');
$request->enableCsrfCookie = false;
$token = $request->getCsrfToken();
@ -302,4 +305,29 @@ class RequestTest extends TestCase
$request = new Request();
$this->assertEquals(null, $request->getOrigin());
}
public function testGetBodyParams()
{
$body = new MemoryStream();
$body->write('name=value');
$request = new Request();
$request->setMethod('PUT');
$request->setBody($body);
$_POST = ['name' => 'post'];
$this->assertSame(['name' => 'value'], $request->withHeader('Content-Type', 'application/x-www-form-urlencoded')->getBodyParams());
$this->assertSame(['name' => 'post'], $request->withHeader('Content-Type', 'application/x-www-form-urlencoded')->withMethod('POST')->getBodyParams());
$this->assertSame(['name' => 'post'], $request->withHeader('Content-Type', 'multipart/form-data')->withMethod('POST')->getBodyParams());
try {
$request->getBodyParams();
} catch (UnsupportedMediaTypeHttpException $noContentTypeException) {}
$this->assertTrue(isset($noContentTypeException));
try {
$request->withMethod('POST')->getBodyParams();
} catch (UnsupportedMediaTypeHttpException $postWithoutContentTypeException) {}
$this->assertTrue(isset($postWithoutContentTypeException));
}
}

4
tests/framework/web/UrlRuleTest.php

@ -1279,7 +1279,7 @@ class UrlRuleTest extends TestCase
}
/**
* @dataProvider testGetCreateUrlStatusProvider
* @dataProvider dataProviderGetCreateUrlStatus
* @param array $config
* @param array $tests
*/
@ -1316,7 +1316,7 @@ class UrlRuleTest extends TestCase
* - third element is the expected URL
* - fourth element is the expected result of getCreateUrlStatus() method
*/
public function testGetCreateUrlStatusProvider()
public function dataProviderGetCreateUrlStatus()
{
return [
'route' => [

Loading…
Cancel
Save