Skip to content

Commit 0234b80

Browse files
committed
Added check for "*" value in Vary header
Loading a cached response containing a Vary: * header leads to a deserialization error warning, even though it matches the specification. Since these responses can never be served from the cache as per RFC 7234 section 4.1, storing them can be avoided to save disk space and get rid of the warning.
1 parent b09b6a1 commit 0234b80

File tree

3 files changed

+19
-0
lines changed

3 files changed

+19
-0
lines changed

cachecontrol/controller.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,15 @@ def cache_response(self, request, response, body=None, status_codes=None):
293293
if no_store:
294294
return
295295

296+
# https://tools.ietf.org/html/rfc7234#section-4.1:
297+
# A Vary header field-value of "*" always fails to match.
298+
# Storing such a response leads to a deserialization warning
299+
# during cache lookup and is not allowed to ever be served,
300+
# so storing it can be avoided.
301+
if "*" in response_headers.get("vary", ""):
302+
logger.debug('Response header has "Vary: *"')
303+
return
304+
296305
# If we've been given an etag, then keep the response
297306
if self.cache_etags and "etag" in response_headers:
298307
logger.debug("Caching due to etag")

cachecontrol/serialize.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ def prepare_response(self, request, cached):
107107
"""
108108
# Special case the '*' Vary value as it means we cannot actually
109109
# determine if the cached response is suitable for this request.
110+
# This case is also handled in the controller code when creating
111+
# a cache entry, but is left here for backwards compatibility.
110112
if "*" in cached.get("vary", {}):
111113
return
112114

tests/test_cache_control.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ def test_cache_response_no_store_with_etag(self, cc):
112112

113113
assert not cc.cache.set.called
114114

115+
def test_no_cache_with_vary_star(self, cc):
116+
# Vary: * indicates that the response can never be served
117+
# from the cache, so storing it can be avoided.
118+
resp = self.resp({"vary": "*"})
119+
cc.cache_response(self.req(), resp)
120+
121+
assert not cc.cache.set.called
122+
115123
def test_update_cached_response_with_valid_headers(self):
116124
cached_resp = Mock(headers={"ETag": "jfd9094r808", "Content-Length": 100})
117125

0 commit comments

Comments
 (0)