Skip to content

Commit

Permalink
Allow cache headers overwrite
Browse files Browse the repository at this point in the history
  • Loading branch information
Gonzalo Vilaseca committed Oct 14, 2014
1 parent 7321b95 commit b70537b
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 14 deletions.
13 changes: 13 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ private function addCacheControlSection(ArrayNodeDefinition $rootNode)
->arrayNode('cache_control')
->fixXmlConfig('rule')
->children()
->arrayNode('defaults')
->children()
->booleanNode('overwrite')
->info('Default behaviour for cache headers overwriting')
->defaultFalse()
->end()
->end()
->end()
->arrayNode('rules')
->prototype('array')
->children();
Expand All @@ -158,6 +166,11 @@ private function addCacheControlSection(ArrayNodeDefinition $rootNode)
->isRequired()
// todo validate there is some header defined
->children()
->enumNode('overwrite')
->info('Overrides default cache headers overwrite behaviour')
->values(array('default', true, false))
->defaultValue('default')
->end()
->arrayNode('cache_control')
->info('Add the specified cache control directives.')
->children()
Expand Down
5 changes: 5 additions & 0 deletions DependencyInjection/FOSHttpCacheExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ private function loadCacheControl(ContainerBuilder $container, array $config)

foreach ($config['rules'] as $rule) {
$ruleMatcher = $this->parseRuleMatcher($container, $rule['match']);

if ($rule['headers']['defaults']['overwrite'] === 'default') {
$rule['headers']['defaults']['overwrite'] = $config['defaults']['overwrite'];
}

$controlDefinition->addMethodCall('addRule', array($ruleMatcher, $rule['headers']))
;
}
Expand Down
31 changes: 23 additions & 8 deletions EventListener/CacheControlSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ public function onKernelResponse(FilterResponseEvent $event)
$directives = array_intersect_key($options['cache_control'], $this->supportedDirectives);
$extraDirectives = array_diff_key($options['cache_control'], $directives);
if (!empty($directives)) {
$this->setCache($response, $directives);
$this->setCache($response, $directives, $options['defaults']['overwrite']);
}
if (!empty($extraDirectives)) {
$this->setExtraCacheDirectives($response, $extraDirectives);
$this->setExtraCacheDirectives($response, $extraDirectives, $options['defaults']['overwrite']);
}
}

Expand All @@ -136,8 +136,21 @@ public function onKernelResponse(FilterResponseEvent $event)
}
}

private function setCache(Response $response, array $directives)
/**
* Set cache headers
*
* @param Response $response
* @param array $directives
* @param boolean $overwrite
*/
private function setCache(Response $response, array $directives, $overwrite)
{
if ($overwrite) {
$response->setCache($directives);

return;
}

if ('no-cache' === $response->headers->get('cache-control')) {
// this single header is set by default. if its the only thing, we override it.
$response->setCache($directives);
Expand Down Expand Up @@ -165,27 +178,29 @@ private function setCache(Response $response, array $directives)
*
* @param Response $response
* @param array $controls
* @param boolean $overwrite
*/
private function setExtraCacheDirectives(Response $response, array $controls)
private function setExtraCacheDirectives(Response $response, array $controls, $overwrite)
{
$flags = array('must_revalidate', 'proxy_revalidate', 'no_transform', 'no_cache');
$options = array('stale_if_error', 'stale_while_revalidate');

foreach ($flags as $key) {
$flag = str_replace('_', '-', $key);
if (!empty($controls[$key])
&& !$response->headers->hasCacheControlDirective($flag)
&& ($overwrite || !$response->headers->hasCacheControlDirective($flag))
) {
$response->headers->addCacheControlDirective($flag);
$response->headers->addCacheControlDirective($flag);
}
}

foreach ($options as $key) {
$option = str_replace('_', '-', $key);
if (isset($controls[$key])
&& !$response->headers->hasCacheControlDirective($option)
&& ($overwrite || !$response->headers->hasCacheControlDirective($option) )
) {
$response->headers->addCacheControlDirective($option, $controls[$key]);
$response->headers->addCacheControlDirective($option, $controls[$key]);

}
}
}
Expand Down
7 changes: 7 additions & 0 deletions Resources/doc/features/headers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,26 @@ Set caching headers under the ``cache_control`` configuration section,
which consists of a set of rules. When the request matches all criteria under
``match``, the headers under ``headers`` will be set on the response.

By default cache headers are not overwritten if already set.
Header overwrite can be forced either globally, setting ``defaults`` ``overwrite`` to true,
or on a per rule basis setting ``overwrite`` to true under ``headers`` settings.

For instance:

.. code-block:: yaml
# app/config/config.yml
fos_http_cache:
cache_control:
defaults:
overwrite: false
rules:
# only match login.example.com
-
match:
host: ^login.example.com$
headers:
overwrite: true
cache_control: { public: false, max_age: 0, s_maxage: 0 }
last_modified: "-1 hour"
vary: [Accept-Encoding, Accept-Language]
Expand Down
6 changes: 6 additions & 0 deletions Resources/doc/reference/configuration/headers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ parameters described in the ``match`` section, the headers as defined under
``headers`` will be set on the response, if they are not already set. Rules are
checked in the order specified, where the first match wins.

A global setting and a per rule basis ``overwrite`` setting allows to overwrite the
cache headers even if they are already set.

.. code-block:: yaml
# app/config/config.yml
fos_http_cache:
cache_control:
defaults:
overwrite: false
rules:
# only match login.example.com
-
match:
host: ^login.example.com$
headers:
overwrite: true
cache_control:
public: false
max_age: 0
Expand Down
4 changes: 4 additions & 0 deletions Tests/Resources/Fixtures/config/full.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

$container->loadFromExtension('fos_http_cache', array(
'cache_control' => array(
'defaults' => array(
'overwrite' => true
),
'rules' => array(
array(
'match' => array(
Expand All @@ -13,6 +16,7 @@
'additional_cacheable_status' => array(100, 500),
),
'headers' => array(
'overwrite' => false,
'cache_control' => array(
'max_age' => 1,
's_maxage' => 2,
Expand Down
4 changes: 4 additions & 0 deletions Tests/Resources/Fixtures/config/full.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

<config xmlns="http://example.org/schema/dic/fos_http_cache">
<cache-control>
<defaults>
<overwrite>true</overwrite>
</defaults>
<rule>
<match
path="/abc"
Expand All @@ -17,6 +20,7 @@
<additional-cacheable-status>500</additional-cacheable-status>
</match>
<headers last-modified="-1 hour" reverse-proxy-ttl="42">
<overwrite>false</overwrite>
<cache-control
max-age="1"
s-maxage="2"
Expand Down
3 changes: 3 additions & 0 deletions Tests/Resources/Fixtures/config/full.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
fos_http_cache:

cache_control:
defaults:
overwrite: true
rules:
-
match:
Expand All @@ -18,6 +20,7 @@ fos_http_cache:
- 100
- 500
headers:
overwrite: false
cache_control:
max_age: 1
s_maxage: 2
Expand Down
8 changes: 8 additions & 0 deletions Tests/Unit/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public function testSupportsAllConfigFormats()
{
$expectedConfiguration = array(
'cache_control' => array(
'defaults' => array(
'overwrite' => true,
),
'rules' => array(
array(
'match' => array(
Expand All @@ -62,6 +65,7 @@ public function testSupportsAllConfigFormats()
// TODO 'match_response' => '',
),
'headers' => array(
'overwrite' => false,
'cache_control' => array(
'max_age' => 1,
's_maxage' => 2,
Expand Down Expand Up @@ -220,9 +224,13 @@ public function testSplitOptions()
'headers' => array(
'reverse_proxy_ttl' => null,
'vary' => array('Cookie', 'Authorization'),
'overwrite' => 'default',
),
),
),
'defaults' => array(
'overwrite' => false,
),
);
$expectedConfiguration['proxy_client'] = array(
'varnish' => array(
Expand Down
22 changes: 16 additions & 6 deletions Tests/Unit/EventListener/CacheControlSubscriberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function testDefaultHeaders()
{
$event = $this->buildEvent();
$headers = array(
'overwrite' => false,
'last_modified' => '13.07.2003',
'cache_control' => array(
'max_age' => '900',
Expand All @@ -43,7 +44,8 @@ public function testDefaultHeaders()
public function testExtraHeaders()
{
$event = $this->buildEvent();
$headers = array('cache_control' => array(
$headers = array('overwrite' => false,
'cache_control' => array(
'must_revalidate' => true,
'proxy_revalidate' => true,
'no_transform' => true,
Expand All @@ -61,7 +63,8 @@ public function testExtraHeaders()
public function testCompoundHeaders()
{
$event = $this->buildEvent();
$headers = array('cache_control' => array(
$headers = array('overwrite' => false,
'cache_control' => array(
'max_age' => '900',
's_maxage' => '300',
'public' => true,
Expand All @@ -84,6 +87,7 @@ public function testSetNoCacheHeaders()
{
$event = $this->buildEvent();
$headers = array(
'overwrite' => false,
'cache_control' => array(
'max_age' => '0',
's_maxage' => '0',
Expand All @@ -104,7 +108,8 @@ public function testSetNoCacheHeaders()
public function testMergeHeaders()
{
$event = $this->buildEvent();
$headers = array('cache_control' => array(
$headers = array('overwrite' => false,
'cache_control' => array(
'max_age' => '900',
's_maxage' => '300',
'public' => true,
Expand All @@ -130,8 +135,10 @@ public function testMergeHeaders()
public function testMergePublicPrivate()
{
$event = $this->buildEvent();
$headers = array('cache_control' => array(
'private' => true,
$headers = array(
'overwrite' => false,
'cache_control' => array(
'private' => true,
));
$subscriber = $this->getCacheControl($headers);
$response = $event->getResponse();
Expand All @@ -150,6 +157,7 @@ public function testSetOnlyNoCacheHeader()
{
$event = $this->buildEvent();
$headers = array(
'overwrite' => false,
'cache_control' => array(
'no_cache' => true,
),
Expand Down Expand Up @@ -237,7 +245,9 @@ public function testMatchRule()
$request2 = $event2->getRequest();
$response2 = $event2->getResponse();

$headers = array('cache_control' => array(
$headers = array(
'overwrite' => false,
'cache_control' => array(
'max_age' => '900',
's_maxage' => '300',
'public' => true,
Expand Down

0 comments on commit b70537b

Please sign in to comment.