How to configure Yii2 to accept only application/json & application/xml requests? (revoking/disallowing form-data)

I’ve set up my application’s content negotiator for json and XML requests but this does not prevent sending in form-data which in some cases breaks the keys because dots and spaces are being converted to underscores see: Why . (dot) and space are changed to _ (underscores) in PHP $_GET array?

Both setting the content negotiator and the parser does not prevent this and the docs did not mention any “revokable” content types.

'bootstrap' => [
    'log', [
        'class' => 'yiifiltersContentNegotiator',
        'formats' => [
            'application/json' => Response::FORMAT_JSON,
            'application/xml' => Response::FORMAT_XML,
        ],
    ],
]
'components' => [
    'request' => [
            'parsers' => [
                'application/json' => 'yiiwebJsonParser',
            ],
        ],
 ]

Answer

The filter ConentNegotiator used to negotiate response format based on request.

You need to create your own request filter. As an example you can use VerbFilter.

The most common sample could be

class ContentTypeFilter extends Behavior
{
    public $contentTypes = [];

    // other code here ...

    public function beforeAction($event)
    {
        if (!$this->contentTypes) {
            return $event->isValid;
        }

        $contentType = Yii::$app->getRequest()->getContentType();
        if (!in_array($contentType, $this->contentTypes)) {
             $event->isValid = false;
             throw new yiiwebUnsupportedMediaTypeHttpException('Method Not Allowed. This URL can only handle the following request content types: ' . implode(', ', $this->contentTypes) . '.');
        }
    }
}