Add support for safe preference - RFC8674

This commit is contained in:
Loïck Piera 2019-12-06 10:08:42 +01:00
parent 20bf17f6ad
commit 7f2cef759c
No known key found for this signature in database
GPG Key ID: 694BD15C4779FF35
5 changed files with 122 additions and 0 deletions

View File

@ -7,6 +7,8 @@ CHANGELOG
* Deprecate `Response::create()`, `JsonResponse::create()`,
`RedirectResponse::create()`, and `StreamedResponse::create()` methods (use
`__construct()` instead)
* added `Request::preferSafeContent()` and `Response::setContentSafe()` to handle "safe" HTTP preference
according to [RFC 8674](https://tools.ietf.org/html/rfc8674)
5.0.0
-----

View File

@ -199,6 +199,11 @@ class Request
private $isHostValid = true;
private $isForwardedValid = true;
/**
* @var bool|null
*/
private $isSafeContentPreferred;
private static $trustedHeaderSet = -1;
private static $forwardedParams = [
@ -1702,6 +1707,29 @@ class Request
return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
}
/**
* Checks whether the client browser prefers safe content or not according to RFC8674.
*
* @see https://tools.ietf.org/html/rfc8674
*/
public function preferSafeContent(): bool
{
if (null !== $this->isSafeContentPreferred) {
return $this->isSafeContentPreferred;
}
if (!$this->isSecure()) {
// see https://tools.ietf.org/html/rfc8674#section-3
$this->isSafeContentPreferred = false;
return $this->isSafeContentPreferred;
}
$this->isSafeContentPreferred = AcceptHeader::fromString($this->headers->get('Prefer'))->has('safe');
return $this->isSafeContentPreferred;
}
/*
* The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24)
*

View File

@ -1210,6 +1210,22 @@ class Response
}
}
/**
* Mark a response as safe according to RFC8674.
*
* @see https://tools.ietf.org/html/rfc8674
*/
public function setContentSafe(bool $safe = true): void
{
if ($safe) {
$this->headers->set('Preference-Applied', 'safe');
} elseif ('safe' === $this->headers->get('Preference-Applied')) {
$this->headers->remove('Preference-Applied');
}
$this->setVary('Prefer', false);
}
/**
* Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9.
*

View File

@ -2325,6 +2325,64 @@ class RequestTest extends TestCase
[null, ['REMOTE_ADDR', '2.2.2.2'], ['2.2.2.2']],
];
}
/**
* @dataProvider preferSafeContentData
*/
public function testPreferSafeContent($server, bool $safePreferenceExpected)
{
$request = new Request([], [], [], [], [], $server);
$this->assertEquals($safePreferenceExpected, $request->preferSafeContent());
}
public function preferSafeContentData()
{
return [
[[], false],
[
[
'HTTPS' => 'on',
],
false,
],
[
[
'HTTPS' => 'off',
'HTTP_PREFER' => 'safe',
],
false,
],
[
[
'HTTPS' => 'on',
'HTTP_PREFER' => 'safe',
],
true,
],
[
[
'HTTPS' => 'on',
'HTTP_PREFER' => 'unknown-preference',
],
false,
],
[
[
'HTTPS' => 'on',
'HTTP_PREFER' => 'unknown-preference=42, safe',
],
true,
],
[
[
'HTTPS' => 'on',
'HTTP_PREFER' => 'safe, unknown-preference=42',
],
true,
],
];
}
}
class RequestContentProxy extends Request

View File

@ -1040,6 +1040,24 @@ class ResponseTest extends ResponseTestCase
{
$this->assertEquals($reasonPhrase, Response::$statusTexts[$code]);
}
public function testSetContentSafe()
{
$response = new Response();
$this->assertFalse($response->headers->has('Preference-Applied'));
$this->assertFalse($response->headers->has('Vary'));
$response->setContentSafe();
$this->assertSame('safe', $response->headers->get('Preference-Applied'));
$this->assertSame('Prefer', $response->headers->get('Vary'));
$response->setContentSafe(false);
$this->assertFalse($response->headers->has('Preference-Applied'));
$this->assertSame('Prefer', $response->headers->get('Vary'));
}
}
class StringableObject