Varnish 4+上的缓存基于缓存控制头,而不是cookie



我想仅基于缓存控制头在清漆上缓存。如果提到了public或max-age,那么无论cookie如何,页面都应该缓存。如果没有存储或没有缓存,则应该绕过缓存,并使用cookie建立正确的会话连接。不确定我在这里做错了什么。

sub vcl_recv {
if ( req.http.X-Force-Cache )
{
unset req.http.Cookie;
unset req.http.Cache-Control;
unset req.http.pragma;
unset req.http.ttl;
}
if (req.http.Authorization ) {
/* Not cacheable by default */
return (pass);
}
if (req.method == "POST" ) {
#set req.hash_always_miss = true;
return (pass);
}
}
sub vcl_hash {
if ( req.http.X-Force-Cache )
{
hash_data(req.http.X-Force-Cache);
}
}
sub vcl_backend_response {
if ( (beresp.http.Cache-control ~ "(no-cache|no-store)"))
{
#unset bereq.http.Cookie;
#unset beresp.http.Set-cookie;
unset bereq.http.X-Force-Cache;
}
elseif ( ( bereq.http.X-Force-Cache  ) )
{
unset beresp.http.Set-cookie;
unset bereq.http.cookie;
unset beresp.http.cookie;
#    unset beresp.http.Cache-Control;
unset bereq.http.X-Force-Cache;
set beresp.ttl = 7d;
unset beresp.http.Cache-Control;
}
else
{
unset beresp.http.Set-cookie;
unset bereq.http.cookie;
unset beresp.http.cookie;
#    unset beresp.http.Cache-Control;
set bereq.http.X-Force-Cache = "1";
set beresp.ttl = 7d;
unset beresp.http.Cache-Control;
}
}

sub vcl_deliver {
if ( req.http.X-Force-Cache )
{
unset req.http.Cookie;
unset resp.http.Cookie;
unset resp.http.Set-cookie;
return(restart);
}
if (obj.hits > 0) { # Add debug header to see if it's a HIT/MISS and the number of hits, disable when not needed
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}

set resp.http.X-Cache-Hits = obj.hits;
set resp.http.Mobile = req.http.CloudFront-Is-Mobile-Viewer;
set resp.http.X-Device = req.http.X-Device;
set resp.http.X-Force-Cache = req.http.X-Force-Cache;

}

我还想向用户隐藏缓存控制头,以防其被缓存。

在缓存中存储对象

当涉及到尊重Cache-Control报头而忽略Set-Cookie报头时,这应该起作用。

sub vcl_backend response {
if(beresp.http.Cache-Control ~ "private|no-cache|no-store" || beresp.ttl <= 0s) {
set beresp.uncacheable = true;
set beresp.ttl = 120s
}
return (deliver);
}

除非Cache-Control标头中出现no-cacheno-storemax-age=0s-maxage=0,否则此代码将在具有Set-Cookie标头的缓存中存储对象。

它只与vcl_backend_response的Varnish内置VCL行为略有不同。

然而,当这种情况发生时,Set-Cookie标头也将存储在缓存中,这似乎很危险。

也许你想去掉Set-Cookie的标题。以下是有条件地删除Set-Cookie标头的代码:

sub vcl_backend response {
if(beresp.http.Cache-Control ~ "private|no-cache|no-store" || beresp.ttl <= 0s) {
set beresp.uncacheable = true;
set beresp.ttl = 120s
} else {
unset beresp.http.Set-Cookie
}
return (deliver);
}

从缓存中提供对象

我们还需要定义具有Cookie请求标头的传入请求的缓存行为。

这是我要使用的代码:

sub vcl_recv {
if (req.method == "PRI") {
/* This will never happen in properly formed traffic (see: RFC7540) */
return (synth(405));
}
if (!req.http.host &&
req.esi_level == 0 &&
req.proto ~ "^(?i)HTTP/1.1") {
/* In HTTP/1.1, Host is required. */
return (synth(400));
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE" &&
req.method != "PATCH") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.method != "GET" && req.method != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization) {
return (pass);
}
return (hash);
}

这与vcl_recv的Varnish内置VCL的唯一不同之处在于删除了req.http.Cookie检查。

有很多额外的代码可以防止对不可缓存的请求方法进行缓存,或者在发送Authorization标头的情况下进行缓存。

然而,如果你不在乎这些,你也可以使用以下代码:

sub vcl_recv { 
if (req.method == "GET" || req.method == "HEAD") {   
return(hash);
}
}

这将服务于从缓存到可缓存请求方法的所有内容,并在所有其他情况下使用内置的VCL行为。有了vcl_backend_response中的措施,Cache-Control: private, no-cache, no-store标头将确保不可缓存的响应永远不会出现在缓存中。

Varnish内置的VCL行为

重要的是要理解Varnish有一个内置的VCL行为。以下是关于这种行为的各个方面的教程:https://www.varnish-software.com/developers/tutorials/varnish-builtin-vcl.

VCL应该只在对应用程序的命中率或灵活性有不利影响的情况下扩展行为。

请看一下教程,了解我建议的VCL代码的影响。

一体式VCL代码:

以下是您可以用来完成任务的一体式VCL代码。你可能想稍微调整一下:

vcl 4.1;
backend default {
.host = "localhost";
.port = "8080";
}
sub vcl_recv { 
if (req.method == "GET" || req.method == "HEAD") {   
return(hash);
}
}
sub vcl_backend response {
if(beresp.http.Cache-Control ~ "private|no-cache|no-store" || beresp.ttl <= 0s) {
set beresp.uncacheable = true;
set beresp.ttl = 120s
} else {
unset beresp.http.Set-Cookie
}
return (deliver);
}

最新更新