Skip to content

Commit 4c7519c

Browse files
PeteLawrencedbu
authored andcommitted
Added configuration setting for enabling xkey tagging
1 parent ab38a78 commit 4c7519c

File tree

13 files changed

+204
-18
lines changed

13 files changed

+204
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Changelog
66

77
### Added
88

9+
* Support for the Varnish xkey vmod for more efficient cache tagging.
10+
911
* Autoconfigure support for custom context providers.
1012

1113
* Autowiring support for the services in this bundle:

Resources/doc/features/helpers/flash-message.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ action was triggered on the server, and such requests must be sent as POST
2222
(or PUT or other non-cacheable) requests.
2323

2424
The flash message listener is automatically enabled if you configure any of
25-
the :doc:`options under flash_message <../../reference/configuration/flash-message>`.
25+
the :doc:`options under flash_message </reference/configuration/flash-message>`.
2626

2727
.. code-block:: yaml
2828

Resources/doc/features/tagging.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ Basic Configuration
2222
-------------------
2323

2424
First configure your proxy for tagging (:ref:`Varnish <foshttpcache:varnish_tagging>`,
25-
:ref:`Symfony <foshttpcache:symfony_httpcache_tagging>`).
25+
:ref:`Symfony <foshttpcache:symfony_httpcache_tagging>`) and see if you want to
26+
adjust anything in the :doc:`proxy client configuration </reference/configuration/proxy-client>`.
2627
Then enable tagging in your application configuration:
2728

2829
.. code-block:: yaml

Resources/doc/reference/cache-manager.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ Invalidate cache tags::
9494

9595
.. note::
9696

97-
Marking a response with tags can be done through the :doc:`ResponseTagger <../features/tagging>`.
97+
Marking a response with tags can be done through the :doc:`ResponseTagger </features/tagging>`.
9898

9999
.. _flushing:
100100

Resources/doc/reference/configuration/flash-message.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Flash Message Configuration
22
===========================
33

4-
The :doc:`flash message listener <../../features/helpers/flash-message>` is a
4+
The :doc:`flash message listener </features/helpers/flash-message>` is a
55
tool to avoid rendering the flash message into the content of a page. It is
66
another building brick for caching pages for logged in users.
77

Resources/doc/reference/configuration/proxy-client.rst

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ varnish
2929
proxy_client:
3030
varnish:
3131
tags_header: My-Cache-Tags
32+
tag_mode: ban
3233
header_length: 1234
3334
default_ban_headers:
3435
Foo: Bar
@@ -38,13 +39,6 @@ varnish
3839
- 123.123.123.2
3940
base_url: yourwebsite.com
4041
41-
``tags_header``
42-
"""""""""""""""
43-
44-
**type**: ``string`` **default**: ``X-Cache-Tags``
45-
46-
Header for sending tag invalidation requests to Varnish.
47-
4842
``header_length``
4943
"""""""""""""""""
5044

@@ -98,8 +92,37 @@ URL may contain a path. If you access your web application on a port other than
9892
Double-check ``base_url``, for if it is mistyped, no content will be
9993
invalidated.
10094

95+
``tag_mode``
96+
""""""""""""
97+
98+
**type**: ``string`` **options**: ``ban``, ``purgekeys`` **default**: ``ban``
99+
100+
Select whether to invalidate tags using the `xkey vmod`_ or with BAN requests.
101+
102+
Xkey is an efficient way to invalidate Varnish cache entries based on
103+
:doc:`tagging </features/tagging>`.
104+
105+
In mode ``purgekeys``, the bundle will default to using soft purges. If you do
106+
not want to use soft purge (either because your varnish modules version is too
107+
old to support it or because soft purging does not fit your scenario),
108+
additionally set the ``tags_header`` option to ``xkey-purge`` instead of the
109+
default ``xkey-softpurge``.
110+
111+
.. note::
112+
113+
To use the purgekeys method, you need the `xkey vmod`_ enabled and VCL to
114+
handle xkey invalidation requests as explained in the
115+
:ref:`FOSHttpCache library docs on xkey support <foshttpcache:varnish_tagging>`.
116+
117+
``tags_header``
118+
"""""""""""""""
119+
120+
**type**: ``string`` **default**: ``X-Cache-Tags`` if ``tag_mode`` is ``ban``, otherwise ``xkey-softpurge``
121+
122+
Header for sending tag invalidation requests to Varnish.
123+
101124
See the :ref:`FOSHttpCache library docs <foshttpcache:varnish configuration>`
102-
on how to configure Varnish.
125+
on how to configure Varnish to handle tag invalidation requests.
103126

104127
nginx
105128
-----
@@ -233,3 +256,5 @@ Caching Proxy Configuration
233256
You need to configure your caching proxy (Varnish or Nginx) to work with this
234257
bundle. Please refer to the :ref:`FOSHttpCache library’s documentation <foshttpcache:proxy-configuration>`
235258
for more information.
259+
260+
.. _xkey vmod: https://github.com/varnish/varnish-modules/blob/master/docs/vmod_xkey.rst

Resources/doc/reference/configuration/tags.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ tags
33

44
Create tag rules in your application configuration to set tags on responses
55
and invalidate them. See the :doc:`tagging feature chapter </features/tagging>`
6-
for an introduction.
6+
for an introduction. Also have a look at :doc:`configuring the proxy client for cache tagging <proxy-client>`.
77

88
.. include:: /includes/enabled.rst
99

Resources/doc/spelling_word_list.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ admin
22
backend
33
cacheable
44
ETag
5+
friendsofsymfony
56
github
67
hostname
78
invalidations
89
invalidator
10+
javascript
911
login
1012
logout
1113
lookup
@@ -16,10 +18,14 @@ multi
1618
nginx
1719
noop
1820
Packagist
21+
plugin
1922
preflight
23+
purgekeys
2024
redeclaration
25+
softpurge
2126
symfony
2227
subdomains
2328
templating
2429
TTL
30+
xkey
2531
yaml

src/DependencyInjection/Configuration.php

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,52 @@ function ($v) {
134134

135135
throw new InvalidConfigurationException('To enable the user context logout handler, you need to configure a ban capable proxy_client.');
136136
})
137+
->end()
138+
// Determine the default tags header for the varnish client, depending on whether we use BAN or xkey
139+
->validate()
140+
->ifTrue(
141+
function ($v) {
142+
return
143+
array_key_exists('proxy_client', $v)
144+
&& array_key_exists('varnish', $v['proxy_client'])
145+
&& empty($v['proxy_client']['varnish']['tags_header'])
146+
;
147+
}
148+
)
149+
->then(function ($v) {
150+
$v['proxy_client']['varnish']['tags_header'] =
151+
(Varnish::TAG_XKEY === $v['proxy_client']['varnish']['tag_mode'])
152+
? Varnish::DEFAULT_HTTP_HEADER_CACHE_XKEY
153+
: Varnish::DEFAULT_HTTP_HEADER_CACHE_TAGS;
154+
155+
return $v;
156+
})
157+
->end()
158+
// Determine the default tag response header, depending on whether we use BAN or xkey
159+
->validate()
160+
->ifTrue(
161+
function ($v) {
162+
return empty($v['tags']['response_header']);
163+
}
164+
)
165+
->then(function ($v) {
166+
$v['tags']['response_header'] = $this->isVarnishXkey($v) ? 'xkey' : TagHeaderFormatter::DEFAULT_HEADER_NAME;
167+
168+
return $v;
169+
})
170+
->end()
171+
// Determine the default separator for the tags header, depending on whether we use BAN or xkey
172+
->validate()
173+
->ifTrue(
174+
function ($v) {
175+
return empty($v['tags']['separator']);
176+
}
177+
)
178+
->then(function ($v) {
179+
$v['tags']['separator'] = $this->isVarnishXkey($v) ? ' ' : ',';
180+
181+
return $v;
182+
})
137183
;
138184

139185
$this->addCacheableResponseSection($rootNode);
@@ -150,6 +196,14 @@ function ($v) {
150196
return $treeBuilder;
151197
}
152198

199+
private function isVarnishXkey(array $v): bool
200+
{
201+
return array_key_exists('proxy_client', $v)
202+
&& array_key_exists('varnish', $v['proxy_client'])
203+
&& Varnish::TAG_XKEY === $v['proxy_client']['varnish']['tag_mode']
204+
;
205+
}
206+
153207
private function addCacheableResponseSection(ArrayNodeDefinition $rootNode)
154208
{
155209
$rootNode
@@ -362,7 +416,6 @@ private function addProxyClientSection(ArrayNodeDefinition $rootNode)
362416
->end()
363417
->children()
364418
->scalarNode('tags_header')
365-
->defaultValue(Varnish::DEFAULT_HTTP_HEADER_CACHE_TAGS)
366419
->info('HTTP header to use when sending tag invalidation requests to Varnish')
367420
->end()
368421
->scalarNode('header_length')
@@ -373,6 +426,11 @@ private function addProxyClientSection(ArrayNodeDefinition $rootNode)
373426
->info('Map of additional headers to include in each ban request.')
374427
->prototype('scalar')->end()
375428
->end()
429+
->enumNode('tag_mode')
430+
->info('If you can enable the xkey module in Varnish, use the purgekeys mode for more efficient tag handling')
431+
->values(['ban', 'purgekeys'])
432+
->defaultValue('ban')
433+
->end()
376434
->append($this->getHttpDispatcherNode())
377435
->end()
378436
->end()
@@ -580,8 +638,12 @@ private function addTagSection(ArrayNodeDefinition $rootNode)
580638
->info('Service name of a custom ExpressionLanugage to use.')
581639
->end()
582640
->scalarNode('response_header')
583-
->defaultValue(TagHeaderFormatter::DEFAULT_HEADER_NAME)
584-
->info('HTTP header that contains cache tags')
641+
->defaultNull()
642+
->info('HTTP header that contains cache tags. Defaults to xkey-softpurge for Varnish xkey or X-Cache-Tags otherwise')
643+
->end()
644+
->scalarNode('separator')
645+
->defaultNull()
646+
->info('Character(s) to use to separate multiple tags. Defaults to " " for Varnish xkey or "," otherwise')
585647
->end()
586648
->arrayNode('rules')
587649
->prototype('array')
@@ -593,8 +655,8 @@ private function addTagSection(ArrayNodeDefinition $rootNode)
593655
})
594656
->thenInvalid('Configured a tag_expression but ExpressionLanugage is not available')
595657
->end()
596-
->children();
597-
658+
->children()
659+
;
598660
$this->addMatch($rules);
599661

600662
$rules

src/DependencyInjection/FOSHttpCacheExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use FOS\HttpCache\ProxyClient\HttpDispatcher;
1515
use FOS\HttpCache\ProxyClient\ProxyClient;
16+
use FOS\HttpCache\ProxyClient\Varnish;
1617
use FOS\HttpCache\SymfonyCache\KernelDispatcher;
1718
use FOS\HttpCacheBundle\DependencyInjection\Compiler\HashGeneratorPass;
1819
use FOS\HttpCacheBundle\Http\ResponseMatcher\ExpressionResponseMatcher;
@@ -403,8 +404,10 @@ private function loadVarnish(ContainerBuilder $container, XmlFileLoader $loader,
403404
{
404405
$this->createHttpDispatcherDefinition($container, $config['http'], 'fos_http_cache.proxy_client.varnish.http_dispatcher');
405406
$options = [
407+
'tag_mode' => $config['tag_mode'],
406408
'tags_header' => $config['tags_header'],
407409
];
410+
408411
if (!empty($config['header_length'])) {
409412
$options['header_length'] = $config['header_length'];
410413
}
@@ -471,7 +474,9 @@ private function loadCacheTagging(ContainerBuilder $container, XmlFileLoader $lo
471474

472475
$container->setParameter('fos_http_cache.compiler_pass.tag_annotations', true);
473476
$container->setParameter('fos_http_cache.tag_handler.response_header', $config['response_header']);
477+
$container->setParameter('fos_http_cache.tag_handler.separator', $config['separator']);
474478
$container->setParameter('fos_http_cache.tag_handler.strict', $config['strict']);
479+
475480
$loader->load('cache_tagging.xml');
476481
if (class_exists(Application::class)) {
477482
$loader->load('cache_tagging_commands.xml');

0 commit comments

Comments
 (0)