Skip to content

Freckle.App.Cache mishandling Vary header #165

Open
@pbrisbin

Description

The intent of the Vary response header for CDNs it to be handled like this. To summarize,

  1. Lookup a key for a request, get a miss
  2. Get a response
  3. Store the response at that key, along with its Vary header values separately
  4. Lookup a key for a future request, get a hit
  5. See the cached value has some Vary data, compare that to the request's headers
  6. If it doesn't match, get a new response
  7. Store that response at the same key, but with different Vary data
  8. Repeat. At (5), we would find multiple values for a given key and would pick one by the Vary data, if possible

This is not what Freckle.App.Cache does.

What Freckle.App.Cache does is a) base the key on the values of any headers mentioned in the request Vary header (unlikely to even be there) and b) ignore the response Vary header entirely. Point (b) is actually how CloudFront works. Yes, one of the biggest CDNs in the world just ignores this part of the HTTP spec!

Step (7) would require a pretty big re-working of our module, since we don't currently expect multiple CachedResponse values at any given CacheKey.

As a solution, I propose we:

  1. Remove the Vary request header handling (unless I'm missing something, it's unlikely to ever even be used)
  2. Decide if we should implement Fastly's correct logic, or not
  3. If not, we need some way for users of this library to indicate what (if any) request headers should always factor into the cache-key.

Point (3) is how CloudFront works around it's lack of actual Vary handling: you have to specify separately by CachePolicy any headers that, ahem, vary, such that they should be incorporated into a cache key

This is not a super impactful bug for us here, since our HTTP interactions don't involve CORS. For reasons I won't go into, mishandling Vary: Origin can lead to CORS bugs. This is the only reason I'm aware of how this all is meant to work.

For us, correct Vary support is most important for: Accept-Encoding and Accept-Language.

Mishandling Vary: Accept-Encoding, should be OK. Most systems either always request-and-receive GZip or always request-and-receive not-GZip, making cross-caching unlikely. And even if so, we will still look at the Content-Encoding header and do the Right Thing, regardless of what we requested.

Mishandling Vary: Accept-Language would be bad, and is the main reason to fix this. If a cached response for Accept-Language: en is used for a user with Accept-Language: es, that's obviously no bueno. That said, use of Accept-Language is not wide-spread (though it should be), compared to (e.g.) a ?lang=en query parameter, which is handled correctly by this library.

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    • Status

      👜 To do

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions