清漆3:接受JSON返回HTML

时间:2018-08-01 08:39:48

标签: varnish

我尝试制作REST-API,但清漆始终返回第一个被调用的响应,我不知道为什么。

如果我使用浏览器打开页面,则Varnish返回HTML->确定。 如果我卷曲相同的页面curl -i https://example.com -H "Accept: application/json",Varnish也会返回HTML->这是False。

如我所见,Varnish始终返回第一个缓存的项目,如果这是JSON,则varnish返回JSON,如果这是HTML,则Varnish返回HTML。

没有清漆,一切正常。

1 个答案:

答案 0 :(得分:2)

如果您在同一URL上提供不同的内容类型,则可能要告诉Varnish相应地对缓存进行分区。

事实上,Varnish并没有做太多特别的事情,它的行为就像其他代理一样。如果他们看到一个没有信息的URL,该信息没有指定资源的缓存应如何分区,那么无论是JSON还是常规请求,无论请求类型如何,都将缓存第一个请求并为其提供相同的服务。

因此,您需要告诉Varnish如何对资源的缓存进行分区。

“ Vary”标头

其他代理中最直接,最“ 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";
    }
}