Skip to content

Commit ca3eca3

Browse files
committed
clear response tagger after tagging to not leak tags from one response to the next
1 parent f5da3a9 commit ca3eca3

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ unreleased
1111
* Fixed: Remove the xkey header in vcl_deliver if we are not in debug mode
1212
* Do not cleanup the Vary header and keep the user context hash if we are in debug mode
1313

14+
### Cache Tagging
15+
16+
* Fixed: Clear the ResponseTagger after we tagged a response. Usually PHP uses
17+
a new instance for every request. But for example the hash lookup when using
18+
Symfony HttpCache does two requests in the same PHP process.
19+
1420
2.5.1
1521
-----
1622

doc/response-tagging.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ Before any content is sent out, you need to send the tag header_::
100100
$responseTagger->getTagsHeaderName(),
101101
$responseTagger->getTagsHeaderValue()
102102
));
103+
$responseTagger->clear();
104+
105+
The call to ``clear`` is only relevant if the same PHP process handles multiple
106+
requests. This happens for example when you :doc:`cache on user context <user-context>`
107+
with the Symfony HttpCache.
103108

104109
.. tip::
105110

src/ResponseTagger.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
/**
2222
* Service for Response cache tagging.
2323
*
24+
* Record tags with this class and then either get the tags header or have the
25+
* tagger add the tags to a PSR-7 response.
26+
* Recorded tags are cleared after tagging a response.
27+
*
2428
* @author David de Boer <[email protected]>
2529
* @author David Buchmann <[email protected]>
2630
* @author André Rømcke <[email protected]>
@@ -129,7 +133,18 @@ public function addTags(array $tags)
129133
}
130134

131135
/**
132-
* Set tags on a response.
136+
* Remove all tags that have been recorded.
137+
*
138+
* This is usually called after adding the tags header to a response. It is
139+
* automatically called by the tagResponse method.
140+
*/
141+
public function clear()
142+
{
143+
$this->tags = [];
144+
}
145+
146+
/**
147+
* Set tags on a response and then clear the tags.
133148
*
134149
* @param ResponseInterface $response Original response
135150
* @param bool $replace Whether to replace the current tags
@@ -143,10 +158,13 @@ public function tagResponse(ResponseInterface $response, $replace = false)
143158
return $response;
144159
}
145160

161+
$value = $this->getTagsHeaderValue();
162+
$this->clear();
163+
146164
if ($replace) {
147-
return $response->withHeader($this->getTagsHeaderName(), $this->getTagsHeaderValue());
165+
return $response->withHeader($this->getTagsHeaderName(), $value);
148166
}
149167

150-
return $response->withAddedHeader($this->getTagsHeaderName(), $this->getTagsHeaderValue());
168+
return $response->withAddedHeader($this->getTagsHeaderName(), $value);
151169
}
152170
}

tests/Unit/ResponseTaggerTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ public function testGetTagsHeaderValue()
3939
->getMock();
4040

4141
$tagger = new ResponseTagger(['header_formatter' => $headerFormatter]);
42-
$this->assertFalse($tagger->hasTags());
4342
$tagger->addTags(['post-1', 'test,post']);
4443
$this->assertTrue($tagger->hasTags());
4544
$this->assertEquals('post-1,test_post', $tagger->getTagsHeaderValue());
45+
$this->assertTrue($tagger->hasTags()); // getting the header does not clear the tags
4646
}
4747

4848
public function testTagResponseReplace()
@@ -65,7 +65,9 @@ public function testTagResponseReplace()
6565
->getMock();
6666

6767
$tagger->addTags(['tag-1', 'tag-2']);
68+
6869
$tagger->tagResponse($response, true);
70+
$this->assertFalse($tagger->hasTags());
6971
}
7072

7173
public function testTagResponseAdd()
@@ -88,7 +90,9 @@ public function testTagResponseAdd()
8890
->getMock();
8991

9092
$tagger->addTags(['tag-1', 'tag-2']);
93+
9194
$tagger->tagResponse($response);
95+
$this->assertFalse($tagger->hasTags());
9296
}
9397

9498
public function testTagResponseNoTags()
@@ -144,4 +148,14 @@ public function testUniqueTags()
144148

145149
$this->assertEquals('post-1,post-2,post-3', $tagHandler->getTagsHeaderValue());
146150
}
151+
152+
public function testClear()
153+
{
154+
$tagger = new ResponseTagger();
155+
$this->assertFalse($tagger->hasTags());
156+
$tagger->addTags(['foo', 'bar']);
157+
$this->assertTrue($tagger->hasTags());
158+
$tagger->clear();
159+
$this->assertFalse($tagger->hasTags());
160+
}
147161
}

0 commit comments

Comments
 (0)