Skip to content

Commit db54c40

Browse files
authored
Merge pull request #163 from dkupka/convert_max_age
Controller: Convert max-age to integer before comparsion
2 parents 68f893a + 109f3d4 commit db54c40

File tree

1 file changed

+57
-40
lines changed

1 file changed

+57
-40
lines changed

cachecontrol/controller.py

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -62,27 +62,51 @@ def cache_url(cls, uri):
6262
return cls._urlnorm(uri)
6363

6464
def parse_cache_control(self, headers):
65-
"""
66-
Parse the cache control headers returning a dictionary with values
67-
for the different directives.
68-
"""
65+
known_directives = {
66+
# https://tools.ietf.org/html/rfc7234#section-5.2
67+
'max-age': (int, True,),
68+
'max-stale': (int, False,),
69+
'min-fresh': (int, True,),
70+
'no-cache': (None, False,),
71+
'no-store': (None, False,),
72+
'no-transform': (None, False,),
73+
'only-if-cached' : (None, False,),
74+
'must-revalidate': (None, False,),
75+
'public': (None, False,),
76+
'private': (None, False,),
77+
'proxy-revalidate': (None, False,),
78+
's-maxage': (int, True,)
79+
}
80+
81+
cc_headers = headers.get('cache-control',
82+
headers.get('Cache-Control', ''))
83+
6984
retval = {}
7085

71-
cc_header = 'cache-control'
72-
if 'Cache-Control' in headers:
73-
cc_header = 'Cache-Control'
74-
75-
if cc_header in headers:
76-
parts = headers[cc_header].split(',')
77-
parts_with_args = [
78-
tuple([x.strip().lower() for x in part.split("=", 1)])
79-
for part in parts if -1 != part.find("=")
80-
]
81-
parts_wo_args = [
82-
(name.strip().lower(), 1)
83-
for name in parts if -1 == name.find("=")
84-
]
85-
retval = dict(parts_with_args + parts_wo_args)
86+
for cc_directive in cc_headers.split(','):
87+
parts = cc_directive.split('=', 1)
88+
directive = parts[0].strip()
89+
90+
try:
91+
typ, required = known_directives[directive]
92+
except KeyError:
93+
logger.debug('Ignoring unknown cache-control directive: %s',
94+
directive)
95+
continue
96+
97+
if not typ or not required:
98+
retval[directive] = None
99+
if typ:
100+
try:
101+
retval[directive] = typ(parts[1].strip())
102+
except IndexError:
103+
if required:
104+
logger.debug('Missing value for cache-control '
105+
'directive: %s', directive)
106+
except ValueError:
107+
logger.debug('Invalid value for cache-control directive '
108+
'%s, must be %s', directive, typ.__name__)
109+
86110
return retval
87111

88112
def cached_request(self, request):
@@ -156,8 +180,8 @@ def cached_request(self, request):
156180
freshness_lifetime = 0
157181

158182
# Check the max-age pragma in the cache control header
159-
if 'max-age' in resp_cc and resp_cc['max-age'].isdigit():
160-
freshness_lifetime = int(resp_cc['max-age'])
183+
if 'max-age' in resp_cc:
184+
freshness_lifetime = resp_cc['max-age']
161185
logger.debug('Freshness lifetime from max-age: %i',
162186
freshness_lifetime)
163187

@@ -173,18 +197,12 @@ def cached_request(self, request):
173197
# Determine if we are setting freshness limit in the
174198
# request. Note, this overrides what was in the response.
175199
if 'max-age' in cc:
176-
try:
177-
freshness_lifetime = int(cc['max-age'])
178-
logger.debug('Freshness lifetime from request max-age: %i',
179-
freshness_lifetime)
180-
except ValueError:
181-
freshness_lifetime = 0
200+
freshness_lifetime = cc['max-age']
201+
logger.debug('Freshness lifetime from request max-age: %i',
202+
freshness_lifetime)
182203

183204
if 'min-fresh' in cc:
184-
try:
185-
min_fresh = int(cc['min-fresh'])
186-
except ValueError:
187-
min_fresh = 0
205+
min_fresh = cc['min-fresh']
188206
# adjust our current age by our min fresh
189207
current_age += min_fresh
190208
logger.debug('Adjusted current age from min-fresh: %i',
@@ -260,10 +278,10 @@ def cache_response(self, request, response, body=None,
260278

261279
# Delete it from the cache if we happen to have it stored there
262280
no_store = False
263-
if cc.get('no-store'):
281+
if 'no-store' in cc:
264282
no_store = True
265283
logger.debug('Response header has "no-store"')
266-
if cc_req.get('no-store'):
284+
if 'no-store' in cc_req:
267285
no_store = True
268286
logger.debug('Request header has "no-store"')
269287
if no_store and self.cache.get(cache_url):
@@ -292,13 +310,12 @@ def cache_response(self, request, response, body=None,
292310
# the cache.
293311
elif 'date' in response_headers:
294312
# cache when there is a max-age > 0
295-
if cc and cc.get('max-age'):
296-
if cc['max-age'].isdigit() and int(cc['max-age']) > 0:
297-
logger.debug('Caching b/c date exists and max-age > 0')
298-
self.cache.set(
299-
cache_url,
300-
self.serializer.dumps(request, response, body=body),
301-
)
313+
if 'max-age' in cc and cc['max-age'] > 0:
314+
logger.debug('Caching b/c date exists and max-age > 0')
315+
self.cache.set(
316+
cache_url,
317+
self.serializer.dumps(request, response, body=body),
318+
)
302319

303320
# If the request can expire, it means we should cache it
304321
# in the meantime.

0 commit comments

Comments
 (0)