Purging the Varnish cache from the browser with PHP
In this note I want to show how to purge the Varnish cache in an elegant way. The article describes how to delete pages=objects from the cache using their URLs.
First you need to describe an ACL in the host settings, to allow purging the cache from certain ip addresses. Add the following to the /etc/varnish/default.vcl file. (the file name can be different depending on how your server is configured)
acl purge { "localhost"; "public_ip_address";}
Then add the following lines to vcl_recv:
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
} else {
purge_url(req.url);
error 200 "Purged. Everything is fine";
}
}
This is needed to forbid purging the cache from the outside.
So that Varnish does not cache the purge page itself, add the following lines to vcl_fetch:
if (req.http.host == "www.your_site.com" && req.url == "^/varadm/.*\.(html|php)$") {
return (pass);
}
To exclude POST requests from caching, make sure vcl_recv has these lines:
if (req.request == "POST") {
return (pass);
}
Disable caching for basic auth requests (vcl_recv):
if (req.http.Authorization || req.http.Authenticate)
{
return (pass);
}
To avoid printing a pile of useless information I cleaned up the standard error page output for myself.
In general you can skip this:
sub vcl_error {
set obj.http.Content-Type = "text/html; charset=utf-8";
synthetic {"
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
</head>
<body>
</body>
</html>
"};
return (deliver);
}
Next create the folder where the files will live and go into it. In my case it is /var/www/varadm.
Inside the folder create a couple of files. The first one is index.php with the following content:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Purge Varnish cache</title>
</head>
<style type="text/css">
body {
font-size: 10px;
}
h1 {
font-weight: bold;
color: #000000;
border-bottom: 1px solid #C6EC8C;
margin-bottom: 2em;
}
label {
font-size: 160%;
float: left;
text-align: right;
margin-right: 0.5em;
display: block
}
input[type="text"] {
width: 500px;
}
.submit input {
margin-left: 0em;
margin-bottom: 1em;
}
</style>
<body>
<h1>Makes Varnish purge the supplied URL from its cache</h1>
<form action="purge.php" method="post">
<p><label>URL</label> <input type="text" name="url"></p>
<p><label>HOST</label> <input type="text" name="host" value="<?php echo $_SERVER["HTTP_HOST"] ?>"></p>
<p class="submit"><input value="Submit" type="submit"></p>
</form>
</body>
</html>
The next one is purge.php with this content:
<?php
$fp = fsockopen("127.0.0.1", "80", $errno, $errstr, 2);
$string = $_POST['url'];
$host = $_POST['host'];
$url = str_replace($host, '', $string);
#$url = $_POST['url'];
echo "<center>";
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "PURGE /$url HTTP/1.0\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
echo "<br>";
}
fclose($fp);
echo "<b>" . $host . $url . " was purged </b><br><br>";
echo "<a href=\"/varadm\">Return to varnish admin page<a>";
}
echo "</center>";
?>
Create the settings for our folder in the Apache config directory: /etc/httpd/conf.d/varadm.conf
Alias /varadm /var/www/varadm
<Directory /var/www/varadm>
DirectoryIndex index.html
Options -Indexes +Includes
Order allow,deny
AuthType Basic
AuthUserFile /var/www/varadm/.ok_user
AuthGroupFile /dev/null
AuthName "Enter username/password"
Require valid-user
Satisfy any
Deny from all
</Directory>
What is left is to create a user for basic auth and generate a password for it:
htpasswd -cmb /var/www/varadm/.ok_user user password
Now you can go to your site with the /varadm location:
http://www.your_site.com/varadm
The form has two fields. One is URL, the second one takes the value www.your_site.com. Put the address of the object you want to delete from the cache into the URL field and press Submit. That’s it. The object is gone.
Strange as it is, Varnish caches the html code of the pages separately, and creates separate cache objects for the static files. Which means that if you changed the code that generates the page and deleted its object from the cache, it does not mean the cache is purged for all the static objects present on that page. It works out pretty well: you don’t need to purge the cache for heavy pages when you change one picture. You can kill the cache object for that picture only.
Sources:
Varnish vcl reference
Script to purge varnish cache
Exploring methods to purge varnish cache
