0

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?

1

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
-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;
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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