@@ -32,6 +32,11 @@ class TagHandler
3232 */
3333 private $ tagsHeader ;
3434
35+ /**
36+ * @var int
37+ */
38+ private $ headerLength ;
39+
3540 /**
3641 * @var array
3742 */
@@ -40,18 +45,20 @@ class TagHandler
4045 /**
4146 * Constructor
4247 *
43- * @param CacheInvalidator $invalidator The invalidator instance.
44- * @param string $tagsHeader Header to use for tags, defaults to X-Cache-Tags.
48+ * @param CacheInvalidator $invalidator The invalidator instance.
49+ * @param string $tagsHeader Header to use for tags, defaults to X-Cache-Tags.
50+ * @param int $headerLength Maximum header size in bytes, defaults to 7500.
4551 *
4652 * @throws UnsupportedProxyOperationException If CacheInvalidator does not support invalidate requests
4753 */
48- public function __construct (CacheInvalidator $ invalidator , $ tagsHeader = 'X-Cache-Tags ' )
54+ public function __construct (CacheInvalidator $ invalidator , $ tagsHeader = 'X-Cache-Tags ' , $ headerLength = 7500 )
4955 {
5056 if (!$ invalidator ->supports (CacheInvalidator::INVALIDATE )) {
5157 throw UnsupportedProxyOperationException::cacheDoesNotImplement ('BAN ' );
5258 }
5359 $ this ->invalidator = $ invalidator ;
5460 $ this ->tagsHeader = $ tagsHeader ;
61+ $ this ->headerLength = $ headerLength ;
5562 }
5663
5764 /**
@@ -64,6 +71,16 @@ public function getTagsHeaderName()
6471 return $ this ->tagsHeader ;
6572 }
6673
74+ /**
75+ * Get the maximum HTTP header length.
76+ *
77+ * @return int
78+ */
79+ public function getHeaderLength ()
80+ {
81+ return $ this ->headerLength ;
82+ }
83+
6784 /**
6885 * Get the value for the HTTP tag header.
6986 *
@@ -112,9 +129,24 @@ public function addTags(array $tags)
112129 */
113130 public function invalidateTags (array $ tags )
114131 {
115- $ tagExpression = sprintf ('(%s)(,.+)?$ ' , implode ('| ' , array_map ('preg_quote ' , $ this ->escapeTags ($ tags ))));
116- $ headers = array ($ this ->tagsHeader => $ tagExpression );
117- $ this ->invalidator ->invalidate ($ headers );
132+ $ escapedTags = array_map ('preg_quote ' , $ this ->escapeTags ($ tags ));
133+
134+ if (mb_strlen (implode ('| ' , $ escapedTags )) >= $ this ->headerLength ) {
135+ /*
136+ * estimate the amount of tags to invalidate by dividing the max
137+ * header length by the largest tag (minus 1 for the implode character)
138+ */
139+ $ tagsize = max (array_map ('mb_strlen ' , $ escapedTags ));
140+ $ elems = floor ($ this ->headerLength / ($ tagsize - 1 )) ? : 1 ;
141+ } else {
142+ $ elems = count ($ escapedTags );
143+ }
144+
145+ foreach (array_chunk ($ escapedTags , $ elems ) as $ tagchunk ) {
146+ $ tagExpression = sprintf ('(%s)(,.+)?$ ' , implode ('| ' , $ tagchunk ));
147+ $ headers = array ($ this ->tagsHeader => $ tagExpression );
148+ $ this ->invalidator ->invalidate ($ headers );
149+ }
118150
119151 return $ this ;
120152 }
0 commit comments