How to make Varnish ignore, not delete cookies

Jason Christa picture Jason Christa · Nov 25, 2010 · Viewed 11.8k times · Source

I want to use Varnish to cache certain pages even in the presence of cookies. There are 3 possibilities that I need to take care of:

  1. An anonymous user is viewing some page
  2. A logged in user is viewing some page with light customization. These customizations are all stored in a signed-cookie and are dynamically populated by Javascript. The vary-cookie http header is not set.
  3. A logged in user is viewing some page with customized data from the database. The vary-cookie http header is set.

The expected behaviors would be:

  1. Cache the page. This is the most basic scenario for Varnish to handle.
  2. Cache the page and do not delete the cookie because some Javascript logic needs it.
  3. Never cache this page because vary-cookie is signalling the cookie contents will affect the output of this page.

I have read some docs on Varnish and I cannot tell if this is the default behavior or if there is some setup I have to do in VCL to make it happen.

Answer

ivy picture ivy · Nov 30, 2010

Only sessions are unique to every client, not necessarily cookies.

What you want makes sense and is possible with Varnish, it is just a matter of carefully crafting your own vcl. Please pay attention to the following parts of the default.vcl:

sub vcl_recv {
    ...
    if (req.http.Authorization || req.http.Cookie) {
      /* Not cacheable by default */
      return (pass);
    }
}


sub vcl_hit {
    if (!obj.cacheable) {
        return (pass);
    }
    ...
}


sub vcl_fetch {
    if (!beresp.cacheable) {
        return (pass);
    }
    if (beresp.http.Set-Cookie) {
        return (pass);
    }
    ...
}

You have to replace these parts with your own logic; i.e. define your own vcl_ functions. By default, requests (vcl_recv) and responses (vcl_fetch) with cookies are not cacheable. You know your back-end application best and you should rewrite the generic caching logic to this specific case. That is, you should define in which case varnish does a lookup, pass or deliver.

In your case, you will have pages (case 1 and 2) without a vary-by cookie, which will be cached and shared by everyone (requests with/without cookies); just don't mind req.http.Cookie in vcl_recv. I wouldn't cache pages (case 3) with a vary-by cookie -or at least not for a long time-, as they can not be shared at all; do a 'pass' in vcl_fetch.