I have been struggling for the past few days with this problem:
Basically, I want to send to a client browser a cookie of the form foo[sha1oftheurl]=[randomvalue]
if and only if the cookie has not already been set.
e.g. If a client browser requests "/page.html", the HTTP response will be like:
resp.http.Set-Cookie = "foo4c9ae249e9e061dd6e30893e03dc10a58cc40ee6=ABCD;"
then, if the same client request "/index.html", the HTTP response will contain a header:
resp.http.Set-Cookie = "foo14fe4559026d4c5b5eb530ee70300c52d99e70d7=QWERTY;"
In the end, the client browser will have 2 cookies:
foo4c9ae249e9e061dd6e30893e03dc10a58cc40ee6=ABCD
foo14fe4559026d4c5b5eb530ee70300c52d99e70d7=QWERTY
Now, that, is not complicated in itself. The following code does it:
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;
}
However, this code does not take into account the case where the Cookie already exists. I need to check that the Cookie does not exists before generating a random value. So I thought about this code:
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();
}
}
The problem is that Varnish does not compute Regular expression at run time. Which leads to this error when I try to compile:
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
One could propose to solve my problem by matching on the "abtest" part of the cookie or even "abtest[a-fA-F0-9]{40}":
if(!req.http.Cookie ~ "abtest[a-fA-F0-9]{40}")
{
set req.http.random-value = random.get_rand();
}
But this code matches any cookie starting by 'abtest' and containing an hexadecimal string of 40 characters. Which means that if a client requests "/page.html" first, then "/index.html", the condition will evaluate to true even if the cookie for the "/index.html" has not been set.
I found in bug report phk or someone else stating that computing regular expressions was extremely expensive which is why they are evaluated during compilation. Considering this, I believe that there is no way of achieving what I want the way I've been trying to.
Is there any way of solving this problem, other than writting a vmod?
Thanks for your help!
-Hugues
ABTest[sha1]=[abtestvalue]
cookie corresponding to this page, if yes, varnish serves the corresponding cached version of the page, if no, varnish (as opposed to the backend) creates the cookie and serves the corresponding cached version of the page.Varnish generating the cookie avoids requesting the backend each time a client comes with no cookie set.