Skip to content

Commit bc9c1ff

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

File tree

4 files changed

+45
-3
lines changed

4 files changed

+45
-3
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+
$tagsHeaderValue = $this->getTagsHeaderValue();
162+
$this->clear();
163+
146164
if ($replace) {
147-
return $response->withHeader($this->getTagsHeaderName(), $this->getTagsHeaderValue());
165+
return $response->withHeader($this->getTagsHeaderName(), $tagsHeaderValue);
148166
}
149167

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

tests/Unit/ResponseTaggerTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public function testGetTagsHeaderValue()
4343
$tagger->addTags(['post-1', 'test,post']);
4444
$this->assertTrue($tagger->hasTags());
4545
$this->assertEquals('post-1,test_post', $tagger->getTagsHeaderValue());
46+
$this->assertTrue($tagger->hasTags()); // getting the header does not clear the tags
4647
}
4748

4849
public function testTagResponseReplace()
@@ -66,6 +67,7 @@ public function testTagResponseReplace()
6667

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

7173
public function testTagResponseAdd()
@@ -89,6 +91,7 @@ public function testTagResponseAdd()
8991

9092
$tagger->addTags(['tag-1', 'tag-2']);
9193
$tagger->tagResponse($response);
94+
$this->assertFalse($tagger->hasTags());
9295
}
9396

9497
public function testTagResponseNoTags()
@@ -144,4 +147,14 @@ public function testUniqueTags()
144147

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

0 commit comments

Comments
 (0)