When using "Full cache of site" (flushAllCaches()), the BAN request sent to Varnish only generates:
ban("obj.http.X-Varnish-Secret == <secret>")
Static assets (JS, CSS, images) served directly by the web server do not have an X-Varnish-Secret header in the cached object — only Drupal-rendered HTML pages do. As a result, assets are never invalidated and continue being served from Varnish cache with an increasing Age header, even after a full cache purge.
Root cause: Two issues combined:
- flushAllCaches() in CacheManager.php only bans by X-Varnish-Secret, which does not match static assets.
- The BAN request is sent by Guzzle to the configured Varnish server address (e.g. varnish, 52.x.x.x), so req.http.host in the BAN request is the internal Varnish hostname — not the public site hostname stored as obj.http.X-Host in cached objects.
Proposed fix:
In CacheManager::flushAllCaches(), add an X-Purge-Host header with the real site hostname:
<?php
$options = [
'headers' => [
'X-Varnish-Purge' => $this->config->get('general.secret'),
'X-Purge-Host' => $this->getRequest()->getHost(),
],
];In varnish/default.vcl, add a second ban expression for assets when /site is banned:
if (req.url == "/site") {
ban("obj.http.X-Varnish-Secret == " + req.http.X-Varnish-Purge);
if (req.http.X-Purge-Host) {
ban("obj.http.X-Host == " + req.http.X-Purge-Host);
} else {
ban("obj.http.X-Host == " + req.http.host);
}
return (synth(200, "Site banned."));
}Steps to reproduce: Cache a JS/CSS asset via Varnish → verify Age is increasing → run "Full cache of site" → request asset again → Age continues increasing (expected: Age: 0, X-Cache: MISS).
Issue fork adv_varnish-3593696
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
carlos romero commented