Varnish VCL - 正则表达式评估

liq*_*ity 3 varnish

这几天我一直在为这个问题苦苦挣扎:

foo[sha1oftheurl]=[randomvalue]基本上,当且仅当 cookie 尚未设置时,我想向客户端浏览器发送以下形式的 cookie 。

例如,如果客户端浏览器请求“/page.html”,则 HTTP 响应将如下所示: resp.http.Set-Cookie = "foo4c9ae249e9e061dd6e30893e03dc10a58cc40ee6=ABCD;"

那么,如果同一个客户端请求“/index.html”,HTTP响应将包含一个标头: resp.http.Set-Cookie = "foo14fe4559026d4c5b5eb530ee70300c52d99e70d7=QWERTY;"

最终,客户端浏览器将会有2个cookie: foo4c9ae249e9e061dd6e30893e03dc10a58cc40ee6=ABCD foo14fe4559026d4c5b5eb530ee70300c52d99e70d7=QWERTY

现在,这本身并不复杂。下面的代码可以做到这一点:

import digest;
import random; ##This vmod does not exist, it's just for the example.


sub vcl_recv()
{
    ## We compute the sha1 of the requested URL and store it in req.http.Url-Sha1
    set req.http.Url-Sha1 = digest.hash_sha1(req.url);
    set req.http.random-value = random.get_rand();
}

sub vcl_deliver()
{
    ## We create a cookie on the client browser by creating a "Set-Cookie" header
    ## In our case the cookie we create is of the form foo[sha1]=[randomvalue]
    ## e.g for a URL "/page.html" the cookie will be foo4c9ae249e9e061dd6e30893e03dc10a58cc40ee6=[randomvalue]
    set resp.http.Set-Cookie = {""} + resp.http.Set-Cookie + "foo"+req.http.Url-Sha1+"="+req.http.random-value;
}
Run Code Online (Sandbox Code Playgroud)

然而,这段代码没有考虑到Cookie已经存在的情况。在生成随机值之前,我需要检查 Cookie 是否不存在。所以我想到了这段代码:

import digest;
    import random;


sub vcl_recv()
{
    ## We compute the sha1 of the requested URL and store it in req.http.Url-Sha1
    set req.http.Url-Sha1 = digest.hash_sha1(req.url);
    set req.http.random-value = random.get_rand();

    set req.http.regex = "abtest"+req.http.Url-Sha1;

    if(!req.http.Cookie ~ req.http.regex)
    {
        set req.http.random-value = random.get_rand();
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是 Varnish 不会在运行时计算正则表达式。当我尝试编译时,这会导致此错误:

Message from VCC-compiler:
Expected CSTR got 'req.http.regex'
(program line 940), at
('input' Line 42 Pos 31)
        if(req.http.Cookie !~ req.http.regex) {
------------------------------##############---

Running VCC-compiler failed, exit 1

VCL compilation failed
Run Code Online (Sandbox Code Playgroud)

有人可以建议通过匹配 cookie 的“abtest”部分甚至“abtest[a-fA-F0-9]{40}”来解决我的问题:

if(!req.http.Cookie ~ "abtest[a-fA-F0-9]{40}")
{
    set req.http.random-value = random.get_rand();
}
Run Code Online (Sandbox Code Playgroud)

但此代码与任何以“abtest”开头且包含 40 个字符的十六进制字符串的 cookie 相匹配。这意味着如果客户端先请求“/page.html”,然后请求“/index.html”,则即使尚未设置“/index.html”的 cookie,条件也会评估为 true。

我在错误报告 phk 或其他人中发现计算正则表达式非常昂贵,这就是为什么在编译期间对它们进行评估的原因。考虑到这一点,我相信没有办法按照我一直在努力的方式实现我想要的目标。

除了编写 vmod 之外,还有其他方法可以解决这个问题吗?

感谢您的帮助!

-休斯

小智 5

有一个窍门!

改变条件

if(!req.http.Cookie ~ req.http.regex)
Run Code Online (Sandbox Code Playgroud)

到:

if(!req.http.Cookie ~ {"" + req.http.regex + ""})
Run Code Online (Sandbox Code Playgroud)

这会将其切换为 CSTR。