How to check the value of a cookie in varnish

cookiesvarnish

I have a cookie for language. I want to check if this cookie is set and to check its value to redirect the user to specific page.
the cookie name is Lang and its value might be En,Fr,or Ar

if (req.http.Cookie ~ "Lang"){
//now i want to check for the cookie value
//if LANG=="Ar"
// set req.url =  req.url "CookieValue"
}

anybody know how to check for cookie value in varnish??
Thanks

Best Answer

Since all the cookies - both name and value - are in the req.http.Cookie string, you should be able to check for both name and value at the same time. Unfortunately, Varnish does not have any specialized methods for dealing with cookies - you must use regular expressions.

It is important to note that cookies are delimited by a semicolon and white space, for example:

cookie1=abc; cookie2=def

We know, therefore that our cookie is either at the start of req.http.Cookie, or is preceded by a semicolon and white space, and either ends with a semicolon, or is at the end of req.http.Cookie. Given this, we can construct a regex that will match our cookie and the semicolon, if any. Something like:

(^|;\s*)(Lang=En)(;|$)

Briefly, going through the above we have:

  • First set of brackets - match the start:
    • ^ means start of string
    • | means OR
    • ; is taken literally (i.e. semicolon)
    • \s means white space
    • * means one or more repetitions of the preceding character
    • Summary: either the start of the string or a semicolon followed by white space
  • Second set of brackets - match the cookie:
    • Lang is the name of the cookie
    • En is the value of the cookie
  • Third set of brackets - match the end
    • ; is taken literally (i.e. semicolon)
    • | means OR
    • $ means end of string
    • Summary: either a semicolon or the end of the string

Using the above, we can check for the cookies and perform some action on them:

if (req.http.Cookie ~ "(^|;\s*)(Lang=En)(;|$)"){
    //do something with En
} elseif (req.http.Cookie ~ "(^|;\s*)(Lang=Fr)(;|$)") {
    //do something with Fr;
}

There may be better ways, or more efficient regexes (unfortunately, varnish doesn't have user defined variables - which means you can't use regex capture groups) - but hopefully this will do the job.

Arguably, you could construct a regex with a capture group using regsub, and set that as a subdomain, perhaps something like:

set req.url = regsub(req.http.Cookie, "(?:^|;\s*)(?:Lang=(.*?))(?:;|$)", "\1.")+"example.com";

In the case of 'Lang=en', you would capture the 'en' add a period (.) and prepend to 'example.com' giving you en.example.com. I'd suggest though directly using a cookie to set the URL - without a lot of error checking - would be a very bad solution. If you just have 3 languages, a couple of if statements and a default would be much safer.

Note: the above is untested, and regexes aren't my forte - expect a few mistakes - but hopefully the premise works.