3

Problem

Varnish is caching pages when I go onto my website anonymously.

I have "Cache Pages for anonymous users" turned on so this is expected.

But when I login it continues to load the cached page for the pages I visited when I was logged out, so the user specific menu never shows and the login button continues to show even though I'm logged in.

I though Varnish didn't work for logged in users and I'm using the default drupal caching system which I thought didn't work for logged in users? How can I prevent this?

Server Set-Up

LEMP Stack - Ubuntu Server 12.04

APC + Memcached

Varnish

Drupal Caching Settings:

Cache pages for anonymous users -> enabled

Minimum cache lifetime -> 0

Expiration of cached pages -> 6 hours

Varnish Module Settings:

Varnish cache clearing: Drupal default

I installed Varnish using this guide and this Varnish config file: http://andrewdunkle.com/how-install-varnish-drupal-7

Browser Caching

I disabled browser caching in Firefox and I still get Varnish cache hits on my homepage however now the menu loads correctly. What does this imply?

2
  • For debugging purposes, please disable caching in your browser. You find this option in the developer tools of most browsers.
    – znerol
    Nov 6, 2013 at 12:40
  • @znerol Ok all done and that causes it to work as expected. What does that imply? Presumably I need to tell the browser to clear it's cache when a user logs in? Nov 6, 2013 at 12:51

2 Answers 2

7

You have two options:

Solution 1: Disallow caching in the browser

In order to prevent a browser from storing and reusing a page, you have to make sure that Cache-Control:no-cache, must-revalidate, post-check=0, pre-check=0 is on the respective (HTML) pages.

You can force this header in sub vcl_deliver. Just make sure that you do not put that header on static assets (like images, CSS and JavaScript files):

sub vcl_deliver {
  set req.http.Cache-Control = "no-cache, must-revalidate, post-check=0, pre-check=0";
}

Solution 2: Ensure that Vary: Cookie is on the response

If you want to force the browser to invalidate its cache whenever the cookies change (i.e. a session is opened), you have to ensure that the Vary: Cookie header is on the response.

sub vcl_deliver {
  if (resp.http.Vary !~ "Cookie") {
    set resp.http.Vary = resp.http.Vary + ", Cookie";
    set resp.http.Vary = regsub(resp.http.Vary, "^,\s*", "");
  }
}

Again, the cache is more effective if you restrict this fragment the page / filetypes which have different contents depending on whether a user is logged in or not.

Safari (at least v5 which is the last one for Windows and the one on iPad 1 and some older iPhones) has a nasty bug. I recommend to add the following snipped in order to deactivate the Safari browser cache:

sub vcl_deliver {
  if (resp.http.X-Generator ~ "Drupal" && req.http.user-agent ~ "Safari" && req.http.user-agent !~ "Chrome") {
    set resp.http.Cache-Control = "no-cache, must-revalidate, post-check=0, pre-check=0";
  }
}

Note: This is a little bit different from the solutions proposed in the comments of the bug report. By placing the snipped into vcl_deliver instead of vcl_fetch we avoid having to separate the bins. Also note that by matching on X-Generator ~ "Drupal" we avoid disabling the browser cache for static assets.

Today (November 2013) I reproduced this misbehavior on Safari 5.1.1 (Windows), 6.1 (Mac OS X 10.8 / Mountain Lion) and 7.0 (iOS 7).

4
  • 1
    Cheers, that's worked great, I used 2. Obviously many websites will have a user menu on every page which changes if you're signed in or not (so you can't restrict the fragment to a page). Is there a clever way of dealing with this problem? (Also are there any resources you'd recommended to read up on for a Varnish Drupal beginner? I'm working through the documentation but I don't understand a lot.) Nov 6, 2013 at 15:05
  • 1
    @DominicWoodman: I recommend to organize a PDF copy of the Varnish Book (linked from the documentation page) and read at least the chapter VCL Basics.
    – znerol
    Nov 7, 2013 at 11:28
  • 1
    I think Solution 2 is a better alternative.
    – Gokul N K
    Nov 19, 2013 at 13:54
  • 1
    @DominicWoodman: Updated answer and included snipped to fix browser cache-bug on Safari 5.
    – znerol
    Nov 30, 2013 at 12:23
1

I choose to use the second option. I added the snippet to my Vanish config file:

/etc/varnish/default.vcl

I added it as it's own standalone snippet as opposed to putting the if function inside the already existing sub vcl_deliver.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.