我尝试制作REST-API,但清漆始终返回第一个被调用的响应,我不知道为什么。
如果我使用浏览器打开页面,则Varnish返回HTML->确定。
如果我卷曲相同的页面curl -i https://example.com -H "Accept: application/json"
,Varnish也会返回HTML->这是False。
如我所见,Varnish始终返回第一个缓存的项目,如果这是JSON,则varnish返回JSON,如果这是HTML,则Varnish返回HTML。
没有清漆,一切正常。
答案 0 :(得分:2)
如果您在同一URL上提供不同的内容类型,则可能要告诉Varnish相应地对缓存进行分区。
事实上,Varnish并没有做太多特别的事情,它的行为就像其他代理一样。如果他们看到一个没有信息的URL,该信息没有指定资源的缓存应如何分区,那么无论是JSON还是常规请求,无论请求类型如何,都将缓存第一个请求并为其提供相同的服务。
因此,您需要告诉Varnish如何对资源的缓存进行分区。
其他代理中最直接,最“ HTTP”兼容的方式是Vary
response 标头。
它告诉代理缓存(在这种情况下为Vanish)根据来自客户端的 标头值对资源的 vary 缓存进行分区。
例如客户发送标头 X:某些值,而您的应用发送标头 Vary:X 是使缓存在 X 的不同值之间不同的原因>。
对于Varnish 3,有一个Accept-Encoding的示例。
本文详细介绍了Vary
的实现挑战-不同的客户端可能会为完全不同的标头发送完全不同的值,从而导致缓存严重分区。因此,您通常希望将可变标头的值归一化为一组已知的期望值。
在您的情况下,您希望变化(并规范化)Accept
header。因此(在vcl_recv
过程中):
if (req.http.Accept) {
if (req.http.Accept ~ "application/json") {
set req.http.Accept = "application/json";
} else {
set req.http.Accept = "text/html";
}
}
接下来,您需要让您的应用实际发送Vary: Accept
(在您的应用源文件中)。另外,如果修改应用程序源文件不可行,则可以抛出一些Varnish VCL:
sub vcl_fetch {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "Accept";
} elseif (beresp.http.Vary !~ "Accept") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", Accept";
}
}