1
votes

I use Varnish 3 and site is on wordpress. The problem is that varnish caches well when I remove all cookies and set-cookie headers. But I need to make varnish to cache pages depending on cookie. (My site content depends on geolocation, so when user logs in first time, I add cookie 'detected_country') First of all I remove all set-cookies headers:

# Drop any cookies Wordpress tries to send back to the client.
sub vcl_fetch {
    if (!(req.url ~ "wp-(login|admin)")) {
          unset beresp.http.set-cookie;
    }
}

Then: by default varnish does not cache requests that have cookies. This is done by default vcl_fetch logic. So I changed default vcl_fetch and commented out cookie ban (see /*|| req.http.Cookie*/):

sub vcl_recv {
 if (req.restarts == 0) {
   if (req.http.x-forwarded-for) {
       set req.http.X-Forwarded-For =
           req.http.X-Forwarded-For + ", " + client.ip;
   } else {
       set req.http.X-Forwarded-For = client.ip;
   }
 }
 if (req.request != "GET" &&
   req.request != "HEAD" &&
   req.request != "PUT" &&
   req.request != "POST" &&
   req.request != "TRACE" &&
   req.request != "OPTIONS" &&
   req.request != "DELETE") {
     /* Non-RFC2616 or CONNECT which is weird. */
     return (pipe);
 }
 if (req.request != "GET" && req.request != "HEAD") {
     /* We only deal with GET and HEAD by default */
     return (pass);
 }
 if (req.http.Authorization /*|| req.http.Cookie*/) {
     /* Not cacheable by default */
     return (pass);
 }
 return (lookup);
 }

After that I expected that varnish will cache page with cookies, but it is not :-( But it should cache ! Isn't it?

If I remove all cookies it caches ok:

sub vcl_recv {
    if (!(req.url ~ "wp-(login|admin)")) {
          remove req.http.Cookie;
    }
}

Please help! I spent a lot of time to find out why it does not cache

1

1 Answers

3
votes

There's nothing in the default VCL, apart from the part you commented out, that will prevent varnish from caching responses for requests with cookies in them. However, your backend server still needs to instruct varnish in the headers to cache a given page. When rendering a page in wordpress you want varnish to cache, add this header to the response:

Cache-Control: public, max-age=600

Where 600 means cache this page for 10 minutes, 86400 would mean for 1 day, etc. If you do this, you have to be really careful that you don't use the geolocation cookie present in the request to generate any part of the response otherwise all users will receive content for the same location, the location of whatever user initiated the request that got cached. If any part of a page needs to use the location cookie, you'll need to render it using an esi:include tag which will generate a separate request to the backend, the results of which you can tell varnish not to cache.