Reputation: 396
I'm using Varnish cache 6.0.6. Sometimes I need to invalidate cache based on URL ignoring GET params and any headers. I use BAN
command for this.
GET commands to retrieve content. The results they receive are different.
curl --user login:secret 'http://example.com/v1/account/123'
curl --user login2:secret2 'http://example.com/v1/account/123?origin=abc'
BAN command to ban both cache.
curl -X BAN example.com -H "X-Ban: /v1/account/123"
Varnish config
if (req.method == "BAN") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed"));
}
ban("obj.http.x-host == " + req.http.host + " && obj.http.x-url ~ " + req.http.X-Ban);
return (synth(200, "Ban added"));
}
However ban command invalidates cache only for the first request. The second request stays cached.
How can I invalidate everything that starts with ^/v1/account/123
?
Upvotes: 0
Views: 1620
Reputation: 4828
I've tested it on a local setup and it does seem to work without any need for changes.
Here's the initial request, you can see that Age: 35
means the item has been stored in cache for 35 seconds.
➜ ~ curl -I localhost/v1/account/123\?origin=abc
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Fri, 15 May 2020 07:26:59 GMT
Content-Length: 216
x-host: localhost
x-url: /v1/account/123?origin=abc
X-Varnish: 32788 32786
Age: 35
Via: 1.1 varnish (Varnish/6.0)
Accept-Ranges: bytes
Connection: keep-alive
The next request issues the ban, using the exact syntax you described in your VCL:
➜ ~ curl -X BAN localhost -H "X-Ban: /v1/account/123"
<!DOCTYPE html>
<html>
<head>
<title>200 Ban added</title>
</head>
<body>
<h1>Error 200 Ban added</h1>
<p>Ban added</p>
<h3>Guru Meditation:</h3>
<p>XID: 14</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
When I execute the initial curl call again, the Age
header is reset to zero, which means the page was not served from cache. Which is the desired outcome.
➜ ~ curl -I localhost/v1/account/123\?origin=abc
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Fri, 15 May 2020 07:40:23 GMT
Content-Length: 213
x-host: localhost
x-url: /v1/account/123?origin=abc
X-Varnish: 16
Age: 0
Via: 1.1 varnish (Varnish/6.0)
Accept-Ranges: bytes
Connection: keep-alive
This is the full VCL is use for this example. Please adjust backend & ACL settings to your needs.
Please make sure x-host
& x-url
are properly set in sub vcl_backend_response
, otherwise your ban statement will not be able to match those values. This is what we call Lurker-friendly bans.
vcl 4.0;
backend default {
.host="localhost";
.port="8080";
}
acl purge {
"localhost";
}
sub vcl_recv {
if (req.method == "BAN") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed"));
}
ban("obj.http.x-host == " + req.http.host + " && obj.http.x-url ~ " + req.http.X-Ban);
return (synth(200, "Ban added"));
}
}
sub vcl_backend_response {
set beresp.http.x-host = bereq.http.host;
set beresp.http.x-url = bereq.url;
}
Upvotes: 2