@@ -62,27 +62,51 @@ def cache_url(cls, uri):
62
62
return cls ._urlnorm (uri )
63
63
64
64
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
+
69
84
retval = {}
70
85
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
+
86
110
return retval
87
111
88
112
def cached_request (self , request ):
@@ -156,8 +180,8 @@ def cached_request(self, request):
156
180
freshness_lifetime = 0
157
181
158
182
# 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' ]
161
185
logger .debug ('Freshness lifetime from max-age: %i' ,
162
186
freshness_lifetime )
163
187
@@ -173,18 +197,12 @@ def cached_request(self, request):
173
197
# Determine if we are setting freshness limit in the
174
198
# request. Note, this overrides what was in the response.
175
199
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 )
182
203
183
204
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' ]
188
206
# adjust our current age by our min fresh
189
207
current_age += min_fresh
190
208
logger .debug ('Adjusted current age from min-fresh: %i' ,
@@ -260,10 +278,10 @@ def cache_response(self, request, response, body=None,
260
278
261
279
# Delete it from the cache if we happen to have it stored there
262
280
no_store = False
263
- if cc . get ( 'no-store' ) :
281
+ if 'no-store' in cc :
264
282
no_store = True
265
283
logger .debug ('Response header has "no-store"' )
266
- if cc_req . get ( 'no-store' ) :
284
+ if 'no-store' in cc_req :
267
285
no_store = True
268
286
logger .debug ('Request header has "no-store"' )
269
287
if no_store and self .cache .get (cache_url ):
@@ -292,13 +310,12 @@ def cache_response(self, request, response, body=None,
292
310
# the cache.
293
311
elif 'date' in response_headers :
294
312
# 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
+ )
302
319
303
320
# If the request can expire, it means we should cache it
304
321
# in the meantime.
0 commit comments