Skip to content

Commit

Permalink
Merge pull request #464 from FriendsOfSymfony/xkey
Browse files Browse the repository at this point in the history
Added configuration setting for enabling xkey tagging
  • Loading branch information
dbu committed Jun 18, 2018
2 parents ab38a78 + cc7d9b2 commit a2326ed
Show file tree
Hide file tree
Showing 14 changed files with 213 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Changelog

### Added

* Support for the Varnish xkey vmod for more efficient cache tagging.

* Autoconfigure support for custom context providers.

* Autowiring support for the services in this bundle:
Expand Down
2 changes: 1 addition & 1 deletion Resources/doc/features/helpers/flash-message.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ action was triggered on the server, and such requests must be sent as POST
(or PUT or other non-cacheable) requests.

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

.. code-block:: yaml
Expand Down
3 changes: 2 additions & 1 deletion Resources/doc/features/tagging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Basic Configuration
-------------------

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

.. code-block:: yaml
Expand Down
2 changes: 1 addition & 1 deletion Resources/doc/reference/cache-manager.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Invalidate cache tags::

.. note::

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

.. _flushing:

Expand Down
2 changes: 1 addition & 1 deletion Resources/doc/reference/configuration/flash-message.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Flash Message Configuration
===========================

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

Expand Down
41 changes: 33 additions & 8 deletions Resources/doc/reference/configuration/proxy-client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ varnish
proxy_client:
varnish:
tags_header: My-Cache-Tags
tag_mode: ban
header_length: 1234
default_ban_headers:
Foo: Bar
Expand All @@ -38,13 +39,6 @@ varnish
- 123.123.123.2
base_url: yourwebsite.com
``tags_header``
"""""""""""""""

**type**: ``string`` **default**: ``X-Cache-Tags``

Header for sending tag invalidation requests to Varnish.

``header_length``
"""""""""""""""""

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

``tag_mode``
""""""""""""

**type**: ``string`` **options**: ``ban``, ``purgekeys`` **default**: ``ban``

Select whether to invalidate tags using the `xkey vmod`_ or with BAN requests.

Xkey is an efficient way to invalidate Varnish cache entries based on
:doc:`tagging </features/tagging>`.

In mode ``purgekeys``, the bundle will default to using soft purges. If you do
not want to use soft purge (either because your varnish modules version is too
old to support it or because soft purging does not fit your scenario),
additionally set the ``tags_header`` option to ``xkey-purge`` instead of the
default ``xkey-softpurge``.

.. note::

To use the purgekeys method, you need the `xkey vmod`_ enabled and VCL to
handle xkey invalidation requests as explained in the
:ref:`FOSHttpCache library docs on xkey support <foshttpcache:varnish_tagging>`.

``tags_header``
"""""""""""""""

**type**: ``string`` **default**: ``X-Cache-Tags`` if ``tag_mode`` is ``ban``, otherwise ``xkey-softpurge``

Header for sending tag invalidation requests to Varnish.

See the :ref:`FOSHttpCache library docs <foshttpcache:varnish configuration>`
on how to configure Varnish.
on how to configure Varnish to handle tag invalidation requests.

nginx
-----
Expand Down Expand Up @@ -233,3 +256,5 @@ Caching Proxy Configuration
You need to configure your caching proxy (Varnish or Nginx) to work with this
bundle. Please refer to the :ref:`FOSHttpCache library’s documentation <foshttpcache:proxy-configuration>`
for more information.

.. _xkey vmod: https://github.com/varnish/varnish-modules/blob/master/docs/vmod_xkey.rst
2 changes: 1 addition & 1 deletion Resources/doc/reference/configuration/tags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ tags

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

.. include:: /includes/enabled.rst

Expand Down
10 changes: 5 additions & 5 deletions Resources/doc/reference/configuration/user-context.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,11 @@ Custom providers need to:
* be tagged with ``fos_http_cache.user_context_provider``.

.. versionadded:: 2.4.0
Autoconfigure support has been added in version 2.4.0 and works from
Symfony 3.3 and above. If autoconfigure is enabled, your custom provider
will be tagged automatically, with a default priority of 0. For older
versions, or if autoconfigure is disabled, or you want to override the
priority, check out the section below.
Since version 2.4.0, context providers are autoconfigured. With
autoconfigure enabled in Symfony 3.3 and newer, your custom providers
are tagged automatically, with a default priority of 0. For older
versions, or if autoconfigure is disabled, or to override the
priority, check out the rest of this section.

If you need context providers to run in a specific order, you can specify the
optional ``priority`` parameter for the tag. The higher the priority, the
Expand Down
10 changes: 10 additions & 0 deletions Resources/doc/spelling_word_list.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
admin
autowired
autowiring
autoconfigure
autoconfigured
backend
cacheable
ETag
friendsofsymfony
github
hostname
invalidations
invalidator
javascript
login
logout
lookup
Expand All @@ -16,10 +22,14 @@ multi
nginx
noop
Packagist
plugin
preflight
purgekeys
redeclaration
softpurge
symfony
subdomains
templating
TTL
xkey
yaml
72 changes: 67 additions & 5 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,52 @@ function ($v) {

throw new InvalidConfigurationException('To enable the user context logout handler, you need to configure a ban capable proxy_client.');
})
->end()
// Determine the default tags header for the varnish client, depending on whether we use BAN or xkey
->validate()
->ifTrue(
function ($v) {
return
array_key_exists('proxy_client', $v)
&& array_key_exists('varnish', $v['proxy_client'])
&& empty($v['proxy_client']['varnish']['tags_header'])
;
}
)
->then(function ($v) {
$v['proxy_client']['varnish']['tags_header'] =
(Varnish::TAG_XKEY === $v['proxy_client']['varnish']['tag_mode'])
? Varnish::DEFAULT_HTTP_HEADER_CACHE_XKEY
: Varnish::DEFAULT_HTTP_HEADER_CACHE_TAGS;

return $v;
})
->end()
// Determine the default tag response header, depending on whether we use BAN or xkey
->validate()
->ifTrue(
function ($v) {
return empty($v['tags']['response_header']);
}
)
->then(function ($v) {
$v['tags']['response_header'] = $this->isVarnishXkey($v) ? 'xkey' : TagHeaderFormatter::DEFAULT_HEADER_NAME;

return $v;
})
->end()
// Determine the default separator for the tags header, depending on whether we use BAN or xkey
->validate()
->ifTrue(
function ($v) {
return empty($v['tags']['separator']);
}
)
->then(function ($v) {
$v['tags']['separator'] = $this->isVarnishXkey($v) ? ' ' : ',';

return $v;
})
;

$this->addCacheableResponseSection($rootNode);
Expand All @@ -150,6 +196,14 @@ function ($v) {
return $treeBuilder;
}

private function isVarnishXkey(array $v): bool
{
return array_key_exists('proxy_client', $v)
&& array_key_exists('varnish', $v['proxy_client'])
&& Varnish::TAG_XKEY === $v['proxy_client']['varnish']['tag_mode']
;
}

private function addCacheableResponseSection(ArrayNodeDefinition $rootNode)
{
$rootNode
Expand Down Expand Up @@ -362,7 +416,6 @@ private function addProxyClientSection(ArrayNodeDefinition $rootNode)
->end()
->children()
->scalarNode('tags_header')
->defaultValue(Varnish::DEFAULT_HTTP_HEADER_CACHE_TAGS)
->info('HTTP header to use when sending tag invalidation requests to Varnish')
->end()
->scalarNode('header_length')
Expand All @@ -373,6 +426,11 @@ private function addProxyClientSection(ArrayNodeDefinition $rootNode)
->info('Map of additional headers to include in each ban request.')
->prototype('scalar')->end()
->end()
->enumNode('tag_mode')
->info('If you can enable the xkey module in Varnish, use the purgekeys mode for more efficient tag handling')
->values(['ban', 'purgekeys'])
->defaultValue('ban')
->end()
->append($this->getHttpDispatcherNode())
->end()
->end()
Expand Down Expand Up @@ -580,8 +638,12 @@ private function addTagSection(ArrayNodeDefinition $rootNode)
->info('Service name of a custom ExpressionLanugage to use.')
->end()
->scalarNode('response_header')
->defaultValue(TagHeaderFormatter::DEFAULT_HEADER_NAME)
->info('HTTP header that contains cache tags')
->defaultNull()
->info('HTTP header that contains cache tags. Defaults to xkey-softpurge for Varnish xkey or X-Cache-Tags otherwise')
->end()
->scalarNode('separator')
->defaultNull()
->info('Character(s) to use to separate multiple tags. Defaults to " " for Varnish xkey or "," otherwise')
->end()
->arrayNode('rules')
->prototype('array')
Expand All @@ -593,8 +655,8 @@ private function addTagSection(ArrayNodeDefinition $rootNode)
})
->thenInvalid('Configured a tag_expression but ExpressionLanugage is not available')
->end()
->children();

->children()
;
$this->addMatch($rules);

$rules
Expand Down
5 changes: 5 additions & 0 deletions src/DependencyInjection/FOSHttpCacheExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use FOS\HttpCache\ProxyClient\HttpDispatcher;
use FOS\HttpCache\ProxyClient\ProxyClient;
use FOS\HttpCache\ProxyClient\Varnish;
use FOS\HttpCache\SymfonyCache\KernelDispatcher;
use FOS\HttpCacheBundle\DependencyInjection\Compiler\HashGeneratorPass;
use FOS\HttpCacheBundle\Http\ResponseMatcher\ExpressionResponseMatcher;
Expand Down Expand Up @@ -403,8 +404,10 @@ private function loadVarnish(ContainerBuilder $container, XmlFileLoader $loader,
{
$this->createHttpDispatcherDefinition($container, $config['http'], 'fos_http_cache.proxy_client.varnish.http_dispatcher');
$options = [
'tag_mode' => $config['tag_mode'],
'tags_header' => $config['tags_header'],
];

if (!empty($config['header_length'])) {
$options['header_length'] = $config['header_length'];
}
Expand Down Expand Up @@ -471,7 +474,9 @@ private function loadCacheTagging(ContainerBuilder $container, XmlFileLoader $lo

$container->setParameter('fos_http_cache.compiler_pass.tag_annotations', true);
$container->setParameter('fos_http_cache.tag_handler.response_header', $config['response_header']);
$container->setParameter('fos_http_cache.tag_handler.separator', $config['separator']);
$container->setParameter('fos_http_cache.tag_handler.strict', $config['strict']);

$loader->load('cache_tagging.xml');
if (class_exists(Application::class)) {
$loader->load('cache_tagging_commands.xml');
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/cache_tagging.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<services>
<service id="fos_http_cache.tag_handler.header_formatter" class="FOS\HttpCache\TagHeaderFormatter\CommaSeparatedTagHeaderFormatter" public="false">
<argument>%fos_http_cache.tag_handler.response_header%</argument>
<argument>%fos_http_cache.tag_handler.separator%</argument>
</service>

<service id="fos_http_cache.http.symfony_response_tagger" class="FOS\HttpCacheBundle\Http\SymfonyResponseTagger" public="true">
Expand Down
4 changes: 4 additions & 0 deletions tests/Unit/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public function testSupportsAllConfigFormats()
],
'proxy_client' => [
'varnish' => [
'tag_mode' => 'ban',
'tags_header' => 'My-Cache-Tags',
'header_length' => 1234,
'default_ban_headers' => ['Foo' => 'Bar'],
Expand Down Expand Up @@ -130,6 +131,7 @@ public function testSupportsAllConfigFormats()
'tag_expressions' => ['"a"', '"b"'],
],
],
'separator' => ',',
],
'invalidation' => [
'enabled' => 'auto',
Expand Down Expand Up @@ -385,6 +387,7 @@ public function testSplitOptions()
'servers' => ['1.1.1.1:80', '2.2.2.2:80'],
],
'tags_header' => 'X-Cache-Tags',
'tag_mode' => 'ban',
],
'nginx' => [
'purge_location' => false,
Expand Down Expand Up @@ -685,6 +688,7 @@ private function getEmptyConfig()
'response_header' => 'X-Cache-Tags',
'expression_language' => null,
'rules' => [],
'separator' => ',',
],
'invalidation' => [
'enabled' => false,
Expand Down

0 comments on commit a2326ed

Please sign in to comment.