Reputation: 44376
I'm having trouble setting up Varnish to properly handle session cookie for ESI-included subrequests.
Three files: index.php
, navigation.php
and footer.php
combined together using ESI, where first two files are stateful, but only index.php
is cachable, while footer.php
is completley stateless.
### index.php
<?php
session_start();
header('Cache-Control: public, s-maxage=10');
header('Surrogate-Control: content="ESI/1.0"');
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Varnish test</title>
</head>
<body>
<esi:include src="http://localhost/WWW/navigation.php" />
<p>Primary content: <?php echo date('r') ?></p>
<esi:include src="http://localhost/WWW/footer.php" />
</body>
</html>
### footer.php
<?php
header('Cache-Control: public, s-maxage=20');
?>
<p>Footer: <?php echo date('r') ?></p>
### navigation.php
<?php
session_start();
if (!isset($_SESSION['counter'])) {
$_SESSION['counter'] = 0;
}
$_SESSION['counter'] += 1;
header('Cache-Control: private');
?>
<p>Navigation: <?php echo $_SESSION['counter'] ?></p>
Varnish VCL configuration:
sub vcl_recv {
set req.http.Surrogate-Capability = "abc=ESI/1.0";
}
sub vcl_fetch {
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
I'd like to see index.php
/footer.php
loaded from the cache, purged every 10/20 seconds, while navigation.php
loaded directly from backend server. Of course the very first request to index.php
cannot be cached as Set-Cookie
header must be set, however footer.php
could be loaded from cache from the very begining.
How could I achieve that? I'm aware that presence of Cookie
header in HTTP request causes cache-miss, but I can't simply delete it.
Upvotes: 3
Views: 1152
Reputation: 1236
Rather a comment than an answer, but to long to fit in one.
The above example lacks of escaping Varnish default VCL [1], Varnish will always append its default logic to your VCL code [2] if you don't avoid it.
In this case you need at least:
sub vcl_recv {
set req.http.Surrogate-Capability = "abc=ESI/1.0";
return (lookup);
}
Varnish also won't cache any response including a Set-Cookie header unless you force it.
[1] https://www.varnish-cache.org/docs/3.0/reference/vcl.html#examples
[2] https://www.varnish-software.com/static/book/VCL_Basics.html#the-vcl-state-engine
Upvotes: 1