Varnish 3 : Accept JSON returns HTML

标签 varnish

我尝试制作一个REST-API,但是 Varnish 总是返回第一个被调用的响应,我也不知道为什么。

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

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

没有Varnish,一切都会按预期进行。

最佳答案

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

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

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

“Vary” header

对于其他代理而言,最直接,最“HTTP”兼容的方式是Vary响应头。

它告诉代理缓存(在这种情况下为Vanish)进行分区,根据来自客户端的 header 值更改资源的缓存。

例如。客户端发送 header X:某值,而您的应用发送 header Vary:X 是使 X 的不同值之间的高速缓存不同的方法。

对于Varnish 3,有一个带有Accept-Encoding的示例。

本文详细介绍了Vary的实现挑战-不同的客户端可能会为完全不同的 header 发送完全不同的值,从而导致严重分区的缓存。因此,您通常希望将可变 header 的值归一化为一组已知的期望值。

在您的情况下,您想更改(并规范化) 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";
    }
}

关于 Varnish 3 : Accept JSON returns HTML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51628871/

相关文章:

ruby-on-rails - Varnishd 是用于 Rails 的正确缓存解决方案吗?

php - 调试Varnish的hit_for_pass对象

centos - pecl 的 Varnish 安装在 whm 上出现错误

varnish - 如何在 Varnish 中缓存动态内容?

varnish - 如何让 Varnish 清除 URL 的所有变体?

caching - Varnish可以生成ETag吗?

php - 您如何扩展Themosis helpers.php函数?

Varnishstat显示0(零)的命中率

Varnish :Purge 说它有效,但不会删除旧内容

caching - 无法使用 "service varnish restart"重新启动 Varnish