Problem/Motivation
This core bug blocks this JSON API contrib module issue: #2831137: [PP-1] Assume the use of the 'api_json' format for routes managed by JSON API.
Observation 1
Currently, the fallback for \Drupal\Core\StackMiddleware\NegotiationMiddleware::getContentType()
(i.e. if no ?_format=
querystring is specified) is this:
// Do HTML last so that it always wins.
return 'html';
And \Drupal\Core\StackMiddleware\NegotiationMiddleware::handle()
does this:
// Determine the request format using the negotiator.
if ($requested_format = $this->getContentType($request)) {
$request->setRequestFormat($requested_format);
}
The end result is that $requested_format
is never empty. It always is set to 'html'
.
Observation 2
Now let's look at \Symfony\Component\HttpFoundation\Request::getRequestFormat()
, which is what the router (and controllers) use to determine the request format
/**
* Gets the request format.
*
* Here is the process to determine the format:
*
* * format defined by the user (with setRequestFormat())
* * _format request parameter
* * $default
*
* @param string $default The default format
*
* @return string The request format
*/
public function getRequestFormat($default = 'html')
{
if (null === $this->format) {
$this->format = $this->get('_format', $default);
}
return $this->format;
}
Result
The result is that Request::getRequestFormat()
's $default
parameter is broken in Drupal, because NegotiationMiddleware
always sets it to 'html'
. Even when there is no _format
request parameter.
In other words: NegotiationMiddleware
breaks the Symfony Request
API.
Proposed resolution
Only let NegotiationMiddleware
call Request::setFormat()
when there actually is a _format
request parameter.
Remaining tasks
TBD
User interface changes
None.
API changes
None.
Data model changes
None.