Skip to content
Permalink
Browse files Browse the repository at this point in the history
[HttpKernel] Remove private headers before storing responses with Htt…
…pCache
  • Loading branch information
nicolas-grekas committed May 4, 2022
1 parent ce4a1a9 commit d2f6322
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/Symfony/Component/HttpKernel/HttpCache/Store.php
Expand Up @@ -26,19 +26,29 @@ class Store implements StoreInterface
{
protected $root;
private $keyCache;
private $locks;
private $locks = [];
private $options;

/**
* Constructor.
*
* The available options are:
*
* * private_headers Set of response headers that should not be stored
* when a response is cached. (default: Set-Cookie)
*
* @throws \RuntimeException
*/
public function __construct(string $root)
public function __construct(string $root, array $options = [])
{
$this->root = $root;
if (!file_exists($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) {
throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root));
}
$this->keyCache = new \SplObjectStorage();
$this->locks = [];
$this->options = array_merge([
'private_headers' => ['Set-Cookie'],
], $options);
}

/**
Expand Down Expand Up @@ -215,6 +225,10 @@ public function write(Request $request, Response $response)
$headers = $this->persistResponse($response);
unset($headers['age']);

foreach ($this->options['private_headers'] as $h) {
unset($headers[strtolower($h)]);
}

array_unshift($entries, [$storedEnv, $headers]);

if (!$this->save($key, serialize($entries))) {
Expand Down
13 changes: 13 additions & 0 deletions src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php
Expand Up @@ -12,8 +12,10 @@
namespace Symfony\Component\HttpKernel\Tests\HttpCache;

use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
use Symfony\Component\HttpKernel\HttpCache\Store;

class StoreTest extends TestCase
Expand Down Expand Up @@ -317,6 +319,17 @@ public function testPurgeHttpAndHttps()
$this->assertEmpty($this->getStoreMetadata($requestHttps));
}

public function testDoesNotStorePrivateHeaders()
{
$request = Request::create('https://example.com/foo');
$response = new Response('foo');
$response->headers->setCookie(Cookie::fromString('foo=bar'));

$this->store->write($request, $response);
$this->assertArrayNotHasKey('set-cookie', $this->getStoreMetadata($request)[0][1]);
$this->assertNotEmpty($response->headers->getCookies());
}

protected function storeSimpleEntry($path = null, $headers = [])
{
if (null === $path) {
Expand Down

5 comments on commit d2f6322

@krasnov23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And i cant find storetest.php

@MacInLife
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t

@DanielRuf
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas please clarify "If the Symfony HTTP cache system is enabled".

Does that mean, that all Symfony applications are impacted by default (the wording tells me that this might not be the case) or what would be the exact steps that would lead to the case, that a Symfony project is impacted?

Is this about https://symfony.com/doc/current/http_cache.html#symfony-reverse-proxy which is not enabled by default?

@stof
Copy link
Member

@stof stof commented on d2f6322 Mar 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is about this symfony reverse proxy, which is not enabled by default.

@DanielRuf
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is about this symfony reverse proxy, which is not enabled by default.

Thanks for the clarification.

Please sign in to comment.