Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions src/Symfony/Component/HttpKernel/HttpCache/Store.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,9 @@ public function write(Request $request, Response $response): string

// read existing cache entries, remove non-varying, and add this one to the list
$entries = [];
$vary = $response->headers->get('vary');
$vary = implode(', ', $response->headers->all('vary'));
foreach ($this->getMetadata($key) as $entry) {
if (!isset($entry[1]['vary'][0])) {
$entry[1]['vary'] = [''];
}

if ($entry[1]['vary'][0] != $vary || !$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) {
if (!$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) {
$entries[] = $entry;
}
}
Expand Down Expand Up @@ -285,7 +281,7 @@ public function invalidate(Request $request)
*/
private function requestsMatch(?string $vary, array $env1, array $env2): bool
{
if (empty($vary)) {
if ('' === ($vary ?? '')) {
return true;
}

Expand Down
121 changes: 121 additions & 0 deletions src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,127 @@ public function testLoadsBodyEval()
$this->assertSame($content, $response->getContent());
}

/**
* Basic case when the second header has a different value.
* Both responses should be cached
*/
public function testWriteWithMultipleVaryAndCachedAllResponse()
{
$req1 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_BAR' => 'bar']);
$content = str_repeat('a', 24).'b'.str_repeat('a', 24);
$res1 = new Response($content, 200, ['vary' => ['Foo', 'Bar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req1, $res1);

$responseLook = $this->store->lookup($req1);
$this->assertSame($content, $responseLook->getContent());

$req2 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_BAR' => 'foobar']);
$content2 = str_repeat('b', 24).'a'.str_repeat('b', 24);
$res2 = new Response($content2, 200, ['vary' => ['Foo', 'Bar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req2, $res2);

$responseLook = $this->store->lookup($req2);
$this->assertSame($content2, $responseLook->getContent());

$responseLook = $this->store->lookup($req1);
$this->assertSame($content, $responseLook->getContent());
}

/**
* Basic case when the second header has the same value on both requests.
* The last response should be cached
*/
public function testWriteWithMultipleVaryAndCachedLastResponse()
{
$req1 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_BAR' => 'bar']);
$content = str_repeat('a', 24).'b'.str_repeat('a', 24);
$res1 = new Response($content, 200, ['vary' => ['Foo', 'Bar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req1, $res1);

$responseLook = $this->store->lookup($req1);
$this->assertSame($content, $responseLook->getContent());

$req2 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_BAR' => 'bar']);
$content2 = str_repeat('b', 24).'a'.str_repeat('b', 24);
$res2 = new Response($content2, 200, ['vary' => ['Foo', 'Bar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req2, $res2);

$responseLook = $this->store->lookup($req2);
$this->assertSame($content2, $responseLook->getContent());

$responseLook = $this->store->lookup($req1);
$this->assertSame($content2, $responseLook->getContent());
}

/**
* Case when a vary value has been removed.
* Both responses should be cached
*/
public function testWriteWithChangingVary()
{
$req1 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_BAR' => 'bar']);
$content = str_repeat('a', 24).'b'.str_repeat('a', 24);
$res1 = new Response($content, 200, ['vary' => ['Foo', 'bar', 'foobar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req1, $res1);

$req2 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_FOOBAR' => 'bar']);
$content2 = str_repeat('b', 24).'a'.str_repeat('b', 24);
$res2 = new Response($content2, 200, ['vary' => ['Foo', 'foobar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req2, $res2);

$responseLook = $this->store->lookup($req2);
$this->assertSame($content2, $responseLook->getContent());

$responseLook = $this->store->lookup($req1);
$this->assertSame($content, $responseLook->getContent());
}

/**
* Case when a vary value has been removed and headers of the new vary list are the same.
* The last response should be cached
*/
public function testWriteWithRemoveVaryAndAllHeadersOnTheList()
{
$req1 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_FOOBAR' => 'bar',]);
$content = str_repeat('a', 24).'b'.str_repeat('a', 24);
$res1 = new Response($content, 200, ['vary' => ['Foo', 'bar', 'foobar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req1, $res1);

$req2 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_FOOBAR' => 'bar']);
$content2 = str_repeat('b', 24).'a'.str_repeat('b', 24);
$res2 = new Response($content2, 200, ['vary' => ['Foo', 'foobar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req2, $res2);

$responseLook = $this->store->lookup($req2);
$this->assertSame($content2, $responseLook->getContent());

$responseLook = $this->store->lookup($req1);
$this->assertSame($content2, $responseLook->getContent());
}

/**
* Case when a vary value has been added and headers of the new vary list are the same.
* The last response should be cached
*/
public function testWriteWithAddingVaryAndAllHeadersOnTheList()
{
$req1 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_FOOBAR' => 'bar']);
$content = str_repeat('a', 24).'b'.str_repeat('a', 24);
$res1 = new Response($content, 200, ['vary' => ['Foo', 'foobar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req1, $res1);

$req2 = Request::create('/foo', 'get', [], [], [], ['HTTP_FOO' => 'foo', 'HTTP_BAR' => 'foobar', 'HTTP_FOOBAR' => 'bar']);
$content2 = str_repeat('b', 24).'a'.str_repeat('b', 24);
$res2 = new Response($content2, 200, ['vary' => ['Foo', 'bar', 'foobar'], 'X-Body-Eval' => 'SSI']);
$this->store->write($req2, $res2);

$responseLook = $this->store->lookup($req2);
$this->assertSame($content2, $responseLook->getContent());

$responseLook = $this->store->lookup($req1);
$this->assertSame($content, $responseLook->getContent());
}

protected function storeSimpleEntry($path = null, $headers = [])
{
$path ??= '/test';
Expand Down
Loading