Vary granularity test

This test is designed to show that browsers do not store multiple copies of objects that have a Vary header on the response, one for each variation, as intermediate caches do. When you serve a response through Fastly, we store each variation of the same URL as a separate cache entry, because different end users may want different variations (eg for language variants). However, a single user rarely changes their

Accept 🔗

Request URLHeadersExpectActualNotes
/format?v=Accept Accept: application/json Seed
/format?v=Accept Accept: application/json HIT Identical request for cachable object => HIT in HTTP cache
/format?v=Accept Accept: text/csv MISS Different varied value => MISS
HIT: Browser doesn't support vary?
/format?v=Accept Accept: application/json MISS Back to original varied header value. HIT for intermediate caches. MISS for browsers because they use vary as a validator only

Accept-Language 🔗

Request URLHeadersExpectActualNotes
/lang?v=Accept-Language Accept-Language: en Seed
/lang?v=Accept-Language Accept-Language: en HIT Identical request for cachable object => HIT in HTTP cache
/lang?v=Accept-Language Accept-Language: jp MISS Different varied value => MISS
HIT: Browser doesn't support vary?
/lang?v=Accept-Language Accept-Language: en MISS Back to original varied header value. HIT for intermediate caches. MISS for browsers because they use vary as a v validator only

Cookie 🔗

Request URLHeadersExpectActualNotes
/util/set-cookie?name=cacheVer&val=1 Setup: set a cookie
/cookie?v=Cookie Seed a new response that varies on cookie
/cookie?v=Cookie HIT Identical request for cachable object => HIT in HTTP cache
/cookie2?v=Cookie Seed new URL, also varying by cookie
/cookie2?v=Cookie HIT Identical request for cachable object => HIT in HTTP cache
/util/set-cookie?name=cacheVer&val=2 Setup: Change the cookie value to prepare for the next test
/cookie?v=Cookie MISS Matches existing URL but cookie has changed and cached object varies on cookie => MISS
/cookie2?v=Cookie MISS Matches existing URL but cookie has changed and cached object varies on cookie => MISS. Changing the one cookie value should affect all requests that vary on cookie.

Link rel=Preload 🔗

Request URLHeadersExpectActualNotes
/preload?ct=image%2Fgif HIT Simple preloaded asset => HIT
/preload?ct=image%2Fgif&c=0 HIT Preloaded asset not normally cachable in HTTP cache => HIT
/preload?ct=image%2Fgif&v=Accept-Encoding HIT Preloaded asset with a vary => HIT
/preload?ct=image%2Fgif&v=Accept-Encoding&c=0 HIT Preloaded asset with vary not normally cachable in HTTP cache => HIT
/preload?ct=image%2Fgif&v=Accept HIT Varying on Accept is risky because the as=image attribute on the preload directive prompts the browser to change the Accept value. It will only match requests whose initiator also prompts the same Accept value (in this case, an image tag).
/preload?ct=image%2Fgif&v=Foo-Header HIT Foo-Header not sent in the preload request nor in the test request => HIT
/preload?ct=image%2Fgif&v=Accept%2C%20Accept-Encoding HIT Multiple headers, including Accept, works if initiator matches as param.

HTTP/2 Push 🔗

Request URLHeadersExpectActualNotes
/push?ct=image%2Fgif HIT Simple push => HIT
Safari (10): Sometimes does not use H2 push cache at all
/push?ct=image%2Fgif&c=0 HIT ... even if it cannot be cached in the HTTP cache (because it should be in the separate preload cache)
/push?ct=image%2Fgif&v=Accept-Encoding&c=0 HIT If the server pushes an object that has a Vary header on the response, it should still be a hit
/push?ct=image%2Fgif&v=Foo-Header&c=0 Foo-Header: 42 MISS Should MISS since the pushed resource varies on Foo-Header, but doesn't know what Foo-Header value we'll be sending. However, some browsers incorrectly ignore Vary on pushed resources.
FF (54): Ignores vary, scores a hit (Bug)
Chrome (59): Ignores vary, scores a hit (Bug)
Safari (10): Ignores vary, scores a hit

Serviceworker-added headers 🔗

Request URLHeadersExpectActualNotes
/sw-header?v=SW-Added-Header MISS A response that varies on a header added by a serviceworker should miss on the first load, because it's not in any cache.
/sw-header?v=SW-Added-Header MISS If the value of the header added by the serviceworker changes on each request, then subsequent identical requests should also not hit the HTTP cache
/sw-header MISS If a Serviceworker adds a header to a request but the server does not vary on it, the response should be available to subsequent requests from the browser cache
/sw-header HIT Identical to previous request, random value added to a header by a serviceworker, but since the server did not vary on that value, it should hit cache.

Serviceworker cache 🔗

Request URLHeadersExpectActualNotes
/util/sw-clear-cache Clear the service worker cache in preparation for the test
/sw-cache?v=Foo-Header&c=0 Foo-Header: 1 MISS First variation of a request for something not in SW cache, expect a MISS
/sw-cache?v=Foo-Header&c=0 Foo-Header: 1 HIT Repeat the first variation. Expect a HIT despite not being cachable in browser cache, because it will be cached in SW cache.
/sw-cache?v=Foo-Header&c=0 Foo-Header: 2 MISS Second variation: Vary on the same header but with a different value, expect a MISS
/sw-cache?v=Foo-Header&c=0 Foo-Header: 2 HIT Repeat second variation, expect a HIT
/sw-cache?v=Foo-Header&c=0 Foo-Header: 1 HIT Back to the first variation. As specified, serviceworker should implement vary like an intermediate cache, not a validator
Chrome (60): Serviceworker cache stores only one variation
/sw-cache?v=Foo-Header&c=0 Foo-Header: 2 HIT Repeat the second variation again, expect a HIT, if cache is storing multiple variations
Chrome (60): Serviceworker cache stores only one variation

304 Not Modified (with matching validator) 🔗

Request URLHeadersExpectActualNotes
/304-special?matching Foo-Header: 1 Seed with a cachable response that varies on Accept (not Foo-Header) but requires revalidation
/304-special?matching Foo-Header: 1 304 Expect initial conditional HIT and revalidation request. Server returns a 304 but with Vary: Accept, Foo-Header (different Vary!). Use cache, update with new Vary header => HIT
/304-special?matching Foo-Header: 1 304 Further requests continue to hit cache.

304 Not Modified (with non-matching validator) 🔗

Request URLHeadersExpectActualNotes
/304-special?non-matching Foo-Header: 1 Seed with a response that Vary: Accept (not Foo-Header), cacheable but requires revalidation
/304-special?non-matching Foo-Header: 2 304 Expect initial conditional HIT and revalidation request. Server returns a 304 but with Vary: Accept, Foo-Header (different Vary!). Use cache, update with new Vary header => HIT
/304-special?non-matching Foo-Header: 1 MISS Spec unclear, but browsers seem to update both the reference request and the cache object, meaning that the cached version is now the variation for fooheader=2. Requesting fooheader=1 should therefore MISS.

Additional notes