Varnish cache responese with "Set-Cookie" header

8,632

Solution 1

I ended up solving the problem like this:

...
# The data on which the hashing will take place
sub vcl_hash {
  hash_data(req.url);
  if (req.http.host) {
        hash_data(req.http.host);
  } else {
        hash_data(server.ip);
  }

  # If the client supports compression, keep that in a different cache
  if (req.http.Accept-Encoding) {
        hash_data(req.http.Accept-Encoding);
  }

  # We add the cookie in the mix with the hash because we actually set cr_layout
  # It should be OK in this particular instance if the number of cookies will not grow
  hash_data(req.http.Cookie);
  return (lookup);
}

# This function is used when a request is sent by our backend
sub vcl_backend_response {
  # If we find our layout cookie we copy it to a header and then we remove it so we can cache the page
  # Later after we deliver the page from cache we set the cookie from the header and then remove that header
  if ( beresp.http.Set-Cookie && beresp.http.Set-Cookie ~ "cr_layout" ) {
    set beresp.http.first-visit = beresp.http.Set-Cookie;
    unset beresp.http.Set-Cookie;
  }
}

sub vcl_deliver {
  # We found that we created a header earlier to remove the cr_layout cookie temporary
  # Now we create that cookie again and remove the header.
  if (resp.http.first-visit) {
    set resp.http.Set-Cookie = resp.http.first-visit;
    unset resp.http.first-visit;
  }
}

Solution 2

The cache key (aka the hash computed in hash_data) is created when receiving the request. The response from the server is not yet received. You cannot change it afterwards.

The two options I can see is :

  • either disabling the cache of response coming with Set-Cookie header (what I think is maybe done by defautl by varnish)
  • or list the parameters in the incoming request you use in your Cookie computation (url, host, accept-language...) and add them to the request hash using hash_data
Share:
8,632

Related videos on Youtube

Bogdan
Author by

Bogdan

Linux Passionate for over a decade. Started my Linux distro (NimbleX) in 2005 and never looked back since.

Updated on September 18, 2022

Comments

  • Bogdan
    Bogdan almost 2 years

    I have a page which sends a "Set-Cookie" header for something like the language depending on the URL. The thing is this page will get a fairly high hit rate but it's not an option right now to strip the "Set-Cookie" header so that Varnish 4 will cache it.

    The documentation only shows how to unset beresp.http.set-cookie or that I can add the cookie to the hash with hash_data(req.http.cookie). As far as I see, adding the cookie to the hash only apply to request Cookies not to the cookies set by the backend.

    I am pretty sure vmod_header could be part of the solution but how would I use it to cache a cookie that I match with beresp.http.Set-Cookie == "language=en_us; path=/; domain=mydomain.tld" and cache this response?