【问题标题】:How to pass data (header?) through in Varnish 4.0如何在 Varnish 4.0 中传递数据(标题?)
【发布时间】:2015-09-07 03:49:26
【问题描述】:

我正在使用devicedetect.vclX-UA-Device 标头发送到我的应用程序,因此它知道要呈现哪个布局。 varnish 将为此标头设置的可能值为mobiledesktop

在退出时,此标头被转换为Vary: User-Agent

现在,作为一个单独的隔离项目,我需要在 resp 对象上设置另一个标头(在发送到客户端之前先发送到我们的 Golang 代理)。此标头将被称为X-Analytics-Device,可能的值是botmobiletabletdesktop

后端服务器确实不需要需要对X-Analytics-Device 做任何事情。只有我们的 Go 代理会解析并删除此标头,然后再将其发送给客户端。

问题是,我需要根据子程序call devicedetect; 的结果来设置X-Analytics-Device 标头,它在vcl_recv 中。我需要最终将其设置在vcl_deliver 中的resp 上,并且我需要知道传递数据的最佳方式。

我能想到的唯一真正可行的方法是(基于我对 Varnish 的有限理解),我需要设置一些其他标头,然后再访问它。

可能是这样的(我暂时省略了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 的?如果它是命中或未命中会发生什么?这有关系吗?这是否会尝试在清漆中缓存此标头(显然不应该)?

我这样做的主要担心是有太多移动的部分,我只是不知道最好的方法。

最终结果是......每个请求都需要检查设备,并且在发出的过程中需要设置标头,而不会将该值与 varnish 中的数据一起缓存,尽管发送也没有什么坏处它到后端,它不需要。

这是我在上面添加伪代码行之前的完整 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";
  }
}

【问题讨论】:

    标签: varnish varnish-vcl


    【解决方案1】:

    @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;
    }
    

    【讨论】:

      【解决方案2】:

      这个链接实际上完美地阐明并回答了我未能表达的所有事情......https://info.varnish-software.com/blog/adding-headers-gain-insight-vcl

      答案是将您需要的所有数据位铲到vcl_recv 中的req 标头中,然后将它们复制到vcl_deliver 中的响应中。

      他陈述了以下,关于为什么它不会被缓存:

      由于 req 对象没有传递给客户端,我们需要将数据从 req 对象复制到 resp。我们在交付时这样做。如果您在 vcl_backend_response 中执行此操作,则标头将存储在缓存中,这可能不是您想要的。

      【讨论】:

        猜你喜欢
        • 2021-09-11
        • 1970-01-01
        • 2014-06-16
        • 1970-01-01
        • 1970-01-01
        • 2013-11-26
        • 2018-06-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多