Skip to content

Commit

Permalink
Make content type detection more robust.
Browse files Browse the repository at this point in the history
Someone could have a detector that wants to find text/html and the
previous change would break that.
  • Loading branch information
markstory committed Jun 26, 2022
1 parent 97d3982 commit 688b27a
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
27 changes: 23 additions & 4 deletions src/Http/ServerRequest.php
Expand Up @@ -129,7 +129,12 @@ class ServerRequest implements ServerRequestInterface
'ssl' => ['env' => 'HTTPS', 'options' => [1, 'on']],
'ajax' => ['env' => 'HTTP_X_REQUESTED_WITH', 'value' => 'XMLHttpRequest'],
'json' => ['accept' => ['application/json'], 'param' => '_ext', 'value' => 'json'],
'xml' => ['accept' => ['application/xml', 'text/xml'], 'param' => '_ext', 'value' => 'xml'],
'xml' => [
'accept' => ['application/xml', 'text/xml'],
'exclude' => ['text/html'],
'param' => '_ext',
'value' => 'xml'
],
];

/**
Expand Down Expand Up @@ -554,11 +559,25 @@ protected function _acceptHeaderDetector(array $detect): bool
{
$content = new ContentTypeNegotiation();
$options = $detect['accept'];
// We add text/html as the browsers often combine xml + html types together.
$options[] = 'text/html';

// Some detectors overlap with the default browser Accept header
// For these types we use an exclude list to refine our content type
// detection.
$exclude = null;
if (!empty($detect['exclude'])) {
$exclude = $detect['exclude'];
$options = array_merge($options, $exclude);
}

$accepted = $content->preferredType($this, $options);
if ($accepted === null) {
return false;
}
if ($exclude && in_array($accepted, $exclude, true)) {
return false;
}

return $accepted !== null && $accepted != 'text/html';
return true;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Http/ContentTypeNegotiationTest.php
Expand Up @@ -36,7 +36,7 @@ public function testPreferredTypeFirefoxHtml()
],
]);
$this->assertEquals('text/html', $content->preferredType($request));
$this->assertEquals('text/html', $content->preferredType($request, ['text/html', 'application/json']));
$this->assertEquals('text/html', $content->preferredType($request, ['text/html', 'application/xml']));
$this->assertEquals('application/xml', $content->preferredType($request, ['application/xml']));
$this->assertNull($content->preferredType($request, ['application/json']));
}
Expand Down

0 comments on commit 688b27a

Please sign in to comment.