If you have a website that you want to be able to cache different versions for country, region or city, and you also do not want to run custom VCL due to the multiple pain points this imposes, but you also want simple purging with acquia purge, consider using custom Vary headers for caching and purging purposes.
Vary header to the rescue
The Vary header is sent by the web server to indicate what makes a HTTP object Vary. This makes a lot of sense with headers like Accept-Encoding. When a server issues a Vary: Accept-Encoding
it tells Varnish that its needs to cache a separate version for every different Accept-Encoding
that is coming from the client. If a client only accepts gzip encoding, Varnish won't serve the version of the page encoded with the Deflate encoding.
How to use a custom Vary header
If you are using a CDN (e.g. Akamai, Cloudflare or Fastly) then you can get these CDN providers to include an extra HTTP header on all requests back to Acquia. You can also add additional custom Vary headers in the response from Drupal.
For Drupal 7
See drupal_add_http_header on the Drupal API. Here is an example that varies on X-MYCUSTOMHEADER
header:
/**
* Implements hook_page_build().
*/
function MYMODULE_page_build(&$page) {
drupal_add_http_header('Vary', 'X-MYCUSTOMHEADER', TRUE);
}
For Drupal 8
-
Custom Module
In Drupal 8 use public function HttpResponse::setHeader
along with an event subscriber. Below you can find an example class and services.yml . For a more detailed example please see Event Systems Overview & How To Subscribe To and Dispatch Events
-
mymodule_event_subscriber.services.yml
services:
mymodule_event_subscriber:
class: '\Drupal\mymodule_event_subscriber\EventSubscriber\MyVaryEventSubscriber'
tags:
- { name: 'event_subscriber' }
-
/EventSubscriber/MyVaryEventSubscriber.php
namespace Drupal\mymodule_event_subscriber\EventSubscriber;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class MyVaryEventSubscriber
*/
class MyVaryEventSubscriber implements EventSubscriberInterface {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events['kernel.response'] = ['onRespond'];
return $events;
}
/**
* This method is called when the kernel.response is dispatched.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The dispatched event.
*/
public function onRespond(FilterResponseEvent $event) {
$response = $event->getResponse();
$response->headers->set('Vary', 'X-MYCUSTOMHEADER');
}
}
-
Contrib Module
The module HTTP Response Headers can also be used to set the Vary header
How to purge all variants in Varnish for a particular URL
Acquia's stock VCL (Varnish Configuration Language) in Acquia Cloud means that if a PURGE
request hits (e.g. it matches a variant in cache), or misses (not in cache), purge
is still called. This means all variants will be removed from Varnish immediately. You can also use acquia purge
Known Issues
You need to ensure that Drupal is not caching pages for anonymous users (as it will not cache per variant, causing much frustration). See above warnings!
You will also need to be running Acquia's stock VCL with no changes to the vcl_hash()
function (e.g. using geo_ip
functionality), as any alterations to this function will cause a regular PURGE to not remove all variants.
Acquia Products
Topics
External Links
- Varnish documentation on purging
- Acquia Purge
- function drupal_add_http_header
- Event Systems Overview & How To Subscribe To and Dispatch Events
- public function HttpResponse::setHeader
- HTTP Response Headers
- Introduce "Vary" page cache response policy
- Page Cache must respect Vary, otherwise it might serve mismatched responses
- Drupal 8 page cache does not respect the Vary header
- Drupal 7 page cache does not respect the Vary header