Skip to content

Commit eaf1f26

Browse files
Toflarnicolas-grekas
authored andcommitted
[HttpKernel] Add skip_response_headers to the HttpCache options
1 parent af57df2 commit eaf1f26

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ CHANGELOG
99
* Add `#[WithHttpStatus]` for defining status codes for exceptions
1010
* Use an instance of `Psr\Clock\ClockInterface` to generate the current date time in `DateTimeValueResolver`
1111
* Add `#[WithLogLevel]` for defining log levels for exceptions
12-
* Allow extending the `Autowire` attribute
12+
* Add `skip_response_headers` to the `HttpCache` options
1313

1414
6.2
1515
---

HttpCache/HttpCache.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
6060
* on responses that don't explicitly state whether the response is
6161
* public or private via a Cache-Control directive. (default: Authorization and Cookie)
6262
*
63+
* * skip_response_headers Set of response headers that are never cached even if a response is cacheable (public).
64+
* (default: Set-Cookie)
65+
*
6366
* * allow_reload Specifies whether the client can force a cache reload by including a
6467
* Cache-Control "no-cache" directive in the request. Set it to ``true``
6568
* for compliance with RFC 2616. (default: false)
@@ -97,6 +100,7 @@ public function __construct(HttpKernelInterface $kernel, StoreInterface $store,
97100
'debug' => false,
98101
'default_ttl' => 0,
99102
'private_headers' => ['Authorization', 'Cookie'],
103+
'skip_response_headers' => ['Set-Cookie'],
100104
'allow_reload' => false,
101105
'allow_revalidate' => false,
102106
'stale_while_revalidate' => 2,
@@ -596,8 +600,17 @@ protected function lock(Request $request, Response $entry): bool
596600
protected function store(Request $request, Response $response)
597601
{
598602
try {
599-
$this->store->write($request, $response);
603+
$restoreHeaders = [];
604+
foreach ($this->options['skip_response_headers'] as $header) {
605+
if (!$response->headers->has($header)) {
606+
continue;
607+
}
600608

609+
$restoreHeaders[$header] = $response->headers->all($header);
610+
$response->headers->remove($header);
611+
}
612+
613+
$this->store->write($request, $response);
601614
$this->record($request, 'store');
602615

603616
$response->headers->set('Age', $response->getAge());
@@ -607,6 +620,10 @@ protected function store(Request $request, Response $response)
607620
if ($this->options['debug']) {
608621
throw $e;
609622
}
623+
} finally {
624+
foreach ($restoreHeaders as $header => $values) {
625+
$response->headers->set($header, $values);
626+
}
610627
}
611628

612629
// now that the response is cached, release the lock

Tests/HttpCache/HttpCacheTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,43 @@ public function testResponsesThatMustNotBeUsedStaleIfError($responseHeaders, $sl
17401740
$this->assertEquals(500, $this->response->getStatusCode());
17411741
}
17421742

1743+
public function testSkipsConfiguredResponseHeadersForStore()
1744+
{
1745+
$storeMock = $this->createMock(StoreInterface::class);
1746+
$storeMock
1747+
->expects($this->once())
1748+
->method('write')
1749+
->with(
1750+
$this->isInstanceOf(Request::class),
1751+
$this->callback(function (Response $response) {
1752+
$this->assertFalse($response->headers->has('Set-Cookie'));
1753+
$this->assertFalse($response->headers->has('Another-One-To-Skip'));
1754+
$this->assertTrue($response->headers->has('Cache-Control'));
1755+
$this->assertTrue($response->headers->has('Another-One-To-Keep'));
1756+
1757+
return true;
1758+
})
1759+
);
1760+
1761+
$this->setNextResponse(200, [
1762+
'Cache-Control' => 'public, s-maxage=20',
1763+
'Set-Cookie' => 'foobar=value; path=/',
1764+
'Another-One-To-Skip' => 'foobar',
1765+
'Another-One-To-Keep' => 'foobar',
1766+
]);
1767+
1768+
$httpCache = new HttpCache($this->kernel, $storeMock, null, [
1769+
'skip_response_headers' => ['Set-Cookie', 'Another-One-To-Skip', 'I-do-Not-Exist'],
1770+
]);
1771+
1772+
$response = $httpCache->handle(Request::create('/'));
1773+
1774+
$this->assertSame('foobar=value; path=/', $response->headers->get('Set-Cookie'));
1775+
$this->assertSame('foobar', $response->headers->get('Another-One-To-Skip'));
1776+
$this->assertSame('foobar', $response->headers->get('Another-One-To-Keep'));
1777+
$this->assertFalse($response->headers->has('I-do-Not-Exist'));
1778+
}
1779+
17431780
public static function getResponseDataThatMustNotBeServedStaleIfError()
17441781
{
17451782
// All data sets assume that a 10s stale-if-error grace period has been configured

0 commit comments

Comments
 (0)