如何在 Varnish 4.0 中传递数据 (header?)
How to pass data (header?) through in Varnish 4.0
我正在使用 devicedetect.vcl
将 X-UA-Device
header 发送到我的应用程序,因此它知道要呈现哪个布局。 varnish 将为此 header 设置的可能值是 mobile
或 desktop
.
在出去的路上,这个 header 被转换为 Vary: User-Agent
。
现在,作为一个独立的独立项目,我需要在 resp
object 上设置另一个 header(它在发送到我们的 Golang 代理之前发送到客户)。此 header 将被称为 X-Analytics-Device
,并且可能的值为 bot
、mobile
、tablet
或 desktop
。
后端服务器不需要对X-Analytics-Device
做任何事情。只有我们的 Go 代理会在将它发送给客户端之前解析并删除这个 header。
问题是,我需要根据 vcl_recv
中子程序 call devicedetect;
的结果设置 X-Analytics-Device
header。我需要最终将它设置在 vcl_deliver
中的 resp
上,我需要知道传递数据的最佳方式。
我能想到的唯一可行的方法(基于我对 Varnish 的有限理解)是我需要设置一些其他的 header,然后再访问它。
可能是这样的(我暂时省略了 bot
):
if (req.http.X-UA-Device ~ "^mobile") {
set req.http.X-UA-Device = "mobile";
set req.http.X-Analytics-Device = "mobile";
} elseif (req.http.X-UA-Device ~ "^tablet") {
set req.http.X-UA-Device = "desktop";
set req.http.X-Analytics-Device = "tablet";
} else {
set req.http.X-UA-Device = "desktop";
set req.http.X-Analytics-Device = "desktop";
}
在此之后...我不知道。 vcl_deliver
需要这么设置吗?
set resp.http.X-Analytics-Device = req.http.X-Analytics-Device;
它是如何从 resp
传递到 req
的?如果命中或未命中会怎样?那有关系吗?这是否会尝试将此 header 缓存在 varnish 中(显然不应该缓存)?
我这样做的主要恐惧是有太多的移动部分我不知道最好的方法。
最终结果是...每个请求都需要检查设备,并且在输出时需要设置 header,而该值不会与清漆中的数据一起缓存,并且虽然将它发送到后端没有什么坏处,但不需要它。
这是我在上面添加 pseudo-code 行之前的完整 VCL。
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
import std;
include "purge.vcl";
include "devicedetect.vcl";
acl purge {
"localhost";
"127.0.0.1";
"10.0.0.0"/8;
}
sub vcl_recv {
call devicedetect;
if (req.http.X-UA-Device ~ "^mobile") {
set req.http.X-UA-Device = "mobile";
} else {
set req.http.X-UA-Device = "desktop";
}
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
if (req.method !~ "^(GET|HEAD|PUT|POST|OPTIONS|DELETE)$") {
return (synth(405));
}
# never cache anything except GET/HEAD
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# don't cache images or assets
if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|ico|tiff|tif|bmp|svg)$") {
return (pass);
}
# fix up the request
unset req.http.cookie;
return (hash);
}
sub vcl_backend_response {
set beresp.do_stream = false;
# device detect
if (bereq.http.X-UA-Device) {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "X-UA-Device";
} elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
}
}
# bypass cache for files > 5 MB
if (std.integer(beresp.http.Content-Length, 0) > 5242880) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# catch obvious reasons we can't cache
if (beresp.http.Set-Cookie) {
set beresp.ttl = 0s;
}
# avoid caching error responses (1m grace period)
if (beresp.status >= 500) {
set beresp.ttl = 1m;
return (deliver);
}
# set times
set beresp.ttl = 24h;
set beresp.grace = 4h;
return (deliver);
}
sub vcl_deliver {
# device detect
if ((req.http.X-UA-Device) && (resp.http.Vary)) {
set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
}
# remove junk headers
unset resp.http.Server;
unset resp.http.Via;
unset resp.http.X-Powered-By;
unset resp.http.X-Runtime;
unset resp.http.X-Varnish;
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
这个 link 实际上完美地澄清并回答了我未能阐明的所有事情...... https://info.varnish-software.com/blog/adding-headers-gain-insight-vcl
答案是将你需要的所有数据位铲到vcl_recv
中的req
headers中,然后将它们复制到vcl_deliver
中的响应中.
他陈述了以下内容,说明了为什么它不会被缓存:
Since the req object is not delivered to the client we need to copy the data from the req object to resp. We do this when we deliver it. If you do it in vcl_backend_response the headers will be stored in the cache and this might not be what you want.
@Tallboy 的回答拯救了我。总结一下你想要做的是:
# set the value in vcl_recv
sub vcl_recv {
set req.http.X-NAVO-AY = "AYAYAYAYAYAYYYYY";
}
# copy the value from req to resp (because it is not done automatically)
sub vcl_deliver {
set resp.http.X-NAVO-AY = req.http.X-NAVO-AY;
}
我正在使用 devicedetect.vcl
将 X-UA-Device
header 发送到我的应用程序,因此它知道要呈现哪个布局。 varnish 将为此 header 设置的可能值是 mobile
或 desktop
.
在出去的路上,这个 header 被转换为 Vary: User-Agent
。
现在,作为一个独立的独立项目,我需要在 resp
object 上设置另一个 header(它在发送到我们的 Golang 代理之前发送到客户)。此 header 将被称为 X-Analytics-Device
,并且可能的值为 bot
、mobile
、tablet
或 desktop
。
后端服务器不需要对X-Analytics-Device
做任何事情。只有我们的 Go 代理会在将它发送给客户端之前解析并删除这个 header。
问题是,我需要根据 vcl_recv
中子程序 call devicedetect;
的结果设置 X-Analytics-Device
header。我需要最终将它设置在 vcl_deliver
中的 resp
上,我需要知道传递数据的最佳方式。
我能想到的唯一可行的方法(基于我对 Varnish 的有限理解)是我需要设置一些其他的 header,然后再访问它。
可能是这样的(我暂时省略了 bot
):
if (req.http.X-UA-Device ~ "^mobile") {
set req.http.X-UA-Device = "mobile";
set req.http.X-Analytics-Device = "mobile";
} elseif (req.http.X-UA-Device ~ "^tablet") {
set req.http.X-UA-Device = "desktop";
set req.http.X-Analytics-Device = "tablet";
} else {
set req.http.X-UA-Device = "desktop";
set req.http.X-Analytics-Device = "desktop";
}
在此之后...我不知道。 vcl_deliver
需要这么设置吗?
set resp.http.X-Analytics-Device = req.http.X-Analytics-Device;
它是如何从 resp
传递到 req
的?如果命中或未命中会怎样?那有关系吗?这是否会尝试将此 header 缓存在 varnish 中(显然不应该缓存)?
我这样做的主要恐惧是有太多的移动部分我不知道最好的方法。
最终结果是...每个请求都需要检查设备,并且在输出时需要设置 header,而该值不会与清漆中的数据一起缓存,并且虽然将它发送到后端没有什么坏处,但不需要它。
这是我在上面添加 pseudo-code 行之前的完整 VCL。
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
import std;
include "purge.vcl";
include "devicedetect.vcl";
acl purge {
"localhost";
"127.0.0.1";
"10.0.0.0"/8;
}
sub vcl_recv {
call devicedetect;
if (req.http.X-UA-Device ~ "^mobile") {
set req.http.X-UA-Device = "mobile";
} else {
set req.http.X-UA-Device = "desktop";
}
if (req.restarts == 0) {
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
}
if (req.method !~ "^(GET|HEAD|PUT|POST|OPTIONS|DELETE)$") {
return (synth(405));
}
# never cache anything except GET/HEAD
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# don't cache images or assets
if (req.url ~ "\.(js|css|jpg|jpeg|png|gif|ico|tiff|tif|bmp|svg)$") {
return (pass);
}
# fix up the request
unset req.http.cookie;
return (hash);
}
sub vcl_backend_response {
set beresp.do_stream = false;
# device detect
if (bereq.http.X-UA-Device) {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "X-UA-Device";
} elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
}
}
# bypass cache for files > 5 MB
if (std.integer(beresp.http.Content-Length, 0) > 5242880) {
set beresp.uncacheable = true;
set beresp.ttl = 120s;
return (deliver);
}
# catch obvious reasons we can't cache
if (beresp.http.Set-Cookie) {
set beresp.ttl = 0s;
}
# avoid caching error responses (1m grace period)
if (beresp.status >= 500) {
set beresp.ttl = 1m;
return (deliver);
}
# set times
set beresp.ttl = 24h;
set beresp.grace = 4h;
return (deliver);
}
sub vcl_deliver {
# device detect
if ((req.http.X-UA-Device) && (resp.http.Vary)) {
set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
}
# remove junk headers
unset resp.http.Server;
unset resp.http.Via;
unset resp.http.X-Powered-By;
unset resp.http.X-Runtime;
unset resp.http.X-Varnish;
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
这个 link 实际上完美地澄清并回答了我未能阐明的所有事情...... https://info.varnish-software.com/blog/adding-headers-gain-insight-vcl
答案是将你需要的所有数据位铲到vcl_recv
中的req
headers中,然后将它们复制到vcl_deliver
中的响应中.
他陈述了以下内容,说明了为什么它不会被缓存:
Since the req object is not delivered to the client we need to copy the data from the req object to resp. We do this when we deliver it. If you do it in vcl_backend_response the headers will be stored in the cache and this might not be what you want.
@Tallboy 的回答拯救了我。总结一下你想要做的是:
# set the value in vcl_recv
sub vcl_recv {
set req.http.X-NAVO-AY = "AYAYAYAYAYAYYYYY";
}
# copy the value from req to resp (because it is not done automatically)
sub vcl_deliver {
set resp.http.X-NAVO-AY = req.http.X-NAVO-AY;
}