Add support for safe preference - RFC8674
This commit is contained in:
parent
20bf17f6ad
commit
7f2cef759c
@ -7,6 +7,8 @@ CHANGELOG
|
|||||||
* Deprecate `Response::create()`, `JsonResponse::create()`,
|
* Deprecate `Response::create()`, `JsonResponse::create()`,
|
||||||
`RedirectResponse::create()`, and `StreamedResponse::create()` methods (use
|
`RedirectResponse::create()`, and `StreamedResponse::create()` methods (use
|
||||||
`__construct()` instead)
|
`__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
|
5.0.0
|
||||||
-----
|
-----
|
||||||
|
@ -199,6 +199,11 @@ class Request
|
|||||||
private $isHostValid = true;
|
private $isHostValid = true;
|
||||||
private $isForwardedValid = true;
|
private $isForwardedValid = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private $isSafeContentPreferred;
|
||||||
|
|
||||||
private static $trustedHeaderSet = -1;
|
private static $trustedHeaderSet = -1;
|
||||||
|
|
||||||
private static $forwardedParams = [
|
private static $forwardedParams = [
|
||||||
@ -1702,6 +1707,29 @@ class Request
|
|||||||
return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
|
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)
|
* The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24)
|
||||||
*
|
*
|
||||||
|
@ -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.
|
* Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9.
|
||||||
*
|
*
|
||||||
|
@ -2325,6 +2325,64 @@ class RequestTest extends TestCase
|
|||||||
[null, ['REMOTE_ADDR', '2.2.2.2'], ['2.2.2.2']],
|
[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
|
class RequestContentProxy extends Request
|
||||||
|
@ -1040,6 +1040,24 @@ class ResponseTest extends ResponseTestCase
|
|||||||
{
|
{
|
||||||
$this->assertEquals($reasonPhrase, Response::$statusTexts[$code]);
|
$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
|
class StringableObject
|
||||||
|
Reference in New Issue
Block a user