Browse Source

Fixes #16010: Fixed `yii\filters\ContentNegotiator` behavior when GET parameters contain an array

tags/2.0.16
Pavel Ivanov 7 years ago committed by Alexander Makarov
parent
commit
35c3ff2fbd
  1. 1
      framework/CHANGELOG.md
  2. 12
      framework/filters/ContentNegotiator.php
  3. 79
      tests/framework/filters/ContentNegotiatorTest.php

1
framework/CHANGELOG.md

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.16 under development
------------------------
- Bug #16010: Fixed `yii\filters\ContentNegotiator` behavior when GET parameters contain an array (rugabarbo)
- Bug #14660: Fixed `yii\caching\DbCache` concurrency issue when set values with the same key (rugabarbo)
- Bug #15988: Fixed bash completion (alekciy)

12
framework/filters/ContentNegotiator.php

@ -10,7 +10,7 @@ namespace yii\filters;
use Yii;
use yii\base\ActionFilter;
use yii\base\BootstrapInterface;
use yii\base\InvalidConfigException;
use yii\web\BadRequestHttpException;
use yii\web\Request;
use yii\web\Response;
use yii\web\UnsupportedMediaTypeHttpException;
@ -165,12 +165,16 @@ class ContentNegotiator extends ActionFilter implements BootstrapInterface
* Negotiates the response format.
* @param Request $request
* @param Response $response
* @throws InvalidConfigException if [[formats]] is empty
* @throws BadRequestHttpException if an array received for GET parameter [[formatParam]].
* @throws UnsupportedMediaTypeHttpException if none of the requested content types is accepted.
*/
protected function negotiateContentType($request, $response)
{
if (!empty($this->formatParam) && ($format = $request->get($this->formatParam)) !== null) {
if (is_array($format)) {
throw new BadRequestHttpException("Invalid data received for GET parameter '{$this->formatParam}'.");
}
if (in_array($format, $this->formats)) {
$response->format = $format;
$response->acceptMimeType = null;
@ -217,6 +221,10 @@ class ContentNegotiator extends ActionFilter implements BootstrapInterface
protected function negotiateLanguage($request)
{
if (!empty($this->languageParam) && ($language = $request->get($this->languageParam)) !== null) {
if (is_array($language)) {
// If an array received, then skip it and use the first of supported languages
return reset($this->languages);
}
if (isset($this->languages[$language])) {
return $this->languages[$language];
}

79
tests/framework/filters/ContentNegotiatorTest.php

@ -0,0 +1,79 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\filters;
use Yii;
use yii\base\Action;
use yii\filters\ContentNegotiator;
use yii\web\Controller;
use yii\web\Request;
use yii\web\Response;
use yiiunit\TestCase;
/**
* @group filters
*/
class ContentNegotiatorTest extends TestCase
{
protected function setUp()
{
parent::setUp();
$this->mockWebApplication();
}
protected function mockActionAndFilter()
{
$action = new Action('test', new Controller('id', Yii::$app));
$filter = new ContentNegotiator([
'request' => new Request(),
'response' => new Response(),
]);
return [$action, $filter];
}
public function testWhenLanguageGETParamIsArray()
{
list($action, $filter) = $this->mockActionAndFilter();
$_SERVER['REQUEST_METHOD'] = 'GET';
$_GET[$filter->languageParam] = [
'foo',
'string-index' => 'bar',
];
$targetLanguage = 'de';
$filter->languages = [$targetLanguage, 'ru', 'en'];
$filter->beforeAction($action);
$this->assertEquals($targetLanguage, Yii::$app->language);
}
/**
* @expectedException yii\web\BadRequestHttpException
* @expectedExceptionMessageRegExp |Invalid data received for GET parameter '.+'|
*/
public function testWhenFormatGETParamIsArray()
{
list($action, $filter) = $this->mockActionAndFilter();
$_SERVER['REQUEST_METHOD'] = 'GET';
$_GET[$filter->formatParam] = [
'format-A',
'string-index' => 'format-B',
];
$filter->formats = [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
];
$filter->beforeAction($action);
}
}
Loading…
Cancel
Save