This is a very simple/generic backend module for Authenticated User Page Caching (Authcache), providing the basics so that it be used to feed upstream reverse proxies and CDNs.

There's really nothing extraordinary on the code, it's a dumb authcache backend which only provides a cookie with the key that you can use upstream.

I have used this module and authcache successfully with Fastly (both anon with sessions and auth), but you need to configure it to do certain things. This could really be done with any Varnish backend, very likely with any other reverse proxy as well (nginx, squid) as long as it allows to do the following recipe.

A nice discussion and documentation is on [#2784873].

Recipe

  1. As soon as the request is get, and before any lookup in the cache (varnish speakers read vcl_recv), look for Drupal.authcache.key in the cookies, extract the value, and add that value to an X-Authcache-Key HTTP header on the request.
  2. After a request has been made to the origin (our site) (varnish speakers read vcl_fetch), modify the Vary response header so that
    1. If not present, add Vary: X-Authcache-Key to the response headers.
    2. If present, append X-Authcache-Key to the Vary response header.
    3. Make sure Cookie is not present either, this will normally be present with Authcache. So remove it from Vary so that it is cached properly. It's good that it's present when it reaches browsers so that it prevents bad local cache.
  3. Before sending the request (varnish speakers read vcl_deliver), remove X-Authcache-Key from the Vary header. (This is optional, I don't think it will affect anything as the request will not be upstream either, but just to be clean, it's nice to do.)

Example VCL for fastly, but should work the same for any Varnish CDN


sub vcl_recv {
...
# set the X-Authcache-Key header
if (req.http.Cookie ~ "Drupal\.authcache\.key=(.*?)(;.*)?$") {
set req.http.X-Authcache-Key = re.group.1;
}
...
}

sub vcl_fetch {
...
# vary on the X-Authcache-Key
if (beresp.http.Vary) {

# Another approach, store original vary as an extension of Cache-Control
# respecting RFC - https://tools.ietf.org/html/rfc7234#section-5.2
# See 5.2.3. Cache Control Extensions
# This is a bit of hack so that 304 responses have this information
# in vcl_deliver, a custom HTTP header for this does not work.
if (beresp.http.Cache-Control) {
set beresp.http.Cache-Control = beresp.http.Cache-Control ", ";
}
set beresp.http.Cache-Control = beresp.http.Cache-Control {"X-Vary=""} beresp.http.Vary {"""};

set beresp.http.Vary = beresp.http.Vary ",X-Authcache-Key";
# Remove an unnecessary Cookie so that we vary only on others
set beresp.http.Vary = regsub(beresp.http.Vary, "Cookie[, ]*", "");
# Fix possible trailing commas in the end
set beresp.http.Vary = regsub(beresp.http.Vary, "[ ]*,[ ]*$", "");
} else {
set beresp.http.Vary = "X-Authcache-Key";
}
...
}

sub vcl_deliver {
...
# 304s are a special case, in which only a few headers are copied from the
# cached object
# From https://tools.ietf.org/html/rfc7232#section-4.1:
# The server generating a 304 response MUST generate any of the
# following header fields that would have been sent in a 200 (OK)
# response to the same request: Cache-Control, Content-Location, Date,
# ETag, Expires, and Vary.

# Restore Original Vary from Cache-Control extension set on vcl_deliver
if (resp.http.Cache-Control ~ "X-Vary=\x22(.*?)\x22") {
set resp.http.Vary = re.group.1;
}

# Remove the Cache-Control custom extension so as it's not needed upstream
set resp.http.Cache-Control = regsub(resp.http.Cache-Control, "(?:, )?X-Vary=\x22.*?\x22", "");
if (!resp.http.Cache-Control) {
unset resp.http.Cache-Control;
}
...
}

Some references:
https://www.fastly.com/blog/best-practices-for-using-the-vary-header
[#2792955]

Short name
authcache_upstream