基于 Cookie 的 Varnish 响应

Varnish response based on Cookie

我有以下 Varnish 配置:


# Default backend definition. Set this to point to your content server.
backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

sub vcl_hash {

    if (req.http.cookie ~ "wordpress_logged_in_[a-z0-9]+") {
        set req.http.X-TMP = regsuball(req.http.cookie, "wordpress_logged_in_[a-z0-9]+=[^;]+(; )?", "; =");
        hash_data(req.http.X-TMP);
        unset req.http.X-TMP;
  }

}

sub vcl_recv {

    #Admin Area
    if (req.url ~ "wp-admin|wp-login") {
        return (pass);
    }


    #woocommerce specifics
    if (req.url ~ "^/(cart|my-account|checkout|addons)") {
        return (pass);
    }

    if ( req.url ~ "\?add-to-cart=" ) {
        return (pass);
    }


    set req.http.cookie = regsuball(req.http.cookie, "wp-settings-\d+=[^;]+(; )?", "");
    set req.http.cookie = regsuball(req.http.cookie, "wp-settings-time-\d+=[^;]+(; )?", "");
    set req.http.cookie = regsuball(req.http.cookie, "wordpress_test_cookie=[^;]+(; )?", "");
    #set req.http.cookie = regsuball(req.http.cookie, "wordpress_logged_in_[a-z0-9]+=[^;]+(; )?", "; =");

    #more woocommerce specifics

    # Unset Cookies except for WordPress admin and WooCommerce pages
    if (!(req.url ~ "(wp-login|wp-admin|cart|my-account/*|wc-api*|checkout|addons|logout|lost-password|product/*)")) {
        unset req.http.cookie;
    }

    # Pass through the WooCommerce dynamic pages
    if (req.url ~ "^/(cart|my-account/*|checkout|wc-api/*|addons|logout|lost-password|product/*)") {
        return (pass);
    }

    # Pass through the WooCommerce add to cart
    if (req.url ~ "\?add-to-cart=" ) {
        return (pass);
    }

    # Pass through the WooCommerce API
    if (req.url ~ "\?wc-api=" ) {
        return (pass);
    }

    if (req.http.cookie == "") {

        unset req.http.cookie;
    }

    return(hash);
}


sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    #
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.

    if (beresp.ttl == 120s) {

        set beresp.ttl = 1h;

    }

    #set beresp.http.host = bereq.http.host;
}

sub vcl_deliver {
    # Happens when we have all the pieces we need, and are about to send the
    # response to the client.
    #
    # You can do accounting or modifying the final object here.
}

我的目标是根据用户是否登录来确保在 URL 上有两个不同的缓存版本。我可以通过名为 [=11] 的 cookie 来确定=].

我试图在 this article 中找到这方面的灵感,但我无法根据客户端是否具有前面提到的 cookie 来获得两个不同的结果。对我来说,无论 cookie 是否存在,都显示相同的缓存内容。

如果能帮助我理解我的问题,我将不胜感激。

看起来你做的一切都是正确的,但我建议你做一些调试。

如果您运行以下命令,Hash标签将出现在varnishlog中:

varnishadm param.set vsl_mask +hash

然后您可以运行以下命令根据 cookie

检查哈希值是否不同
varnishlog -g request -i requrl -i hash -I reqHeader:Cookie

此日志记录命令列出了以下项目:

  • 要求URL
  • cookie header
  • 创建的散列

这应该可以帮助您弄清楚发生了什么。

应用文章中建议的解决方案将产生与登录用户一样多的缓存条目(per-user 缓存)。

如果您想要一个缓存 object 用于来宾,另一个用于所有登录用户,则对基于 cookie 的存在设置的“布尔值”进行哈希处理:

sub vcl_hash {
  if (req.http.cookie ~ "wordpress_logged_in_") {
    hash_data("wordpress_logged_in");
  }
  # the builtin.vcl will take care of also varying cache on Host/IP and URL 
}

只有在存在 cookie 时生成的页面不包含 user-specific 内容,这才是安全的。例如,如果“登录页面”与“注销页面”的不同之处仅在于网站 header 部分中存在“注销”文本。

任何内容绝对是 user-specific 的地方,您不希望应用这样的逻辑。例如,header 文本中的“嗨,约翰”。