Changeset 1506
- Timestamp:
- 12/10/06 16:48:58
- Files:
-
- branches/cherrypy-2.x/cherrypy/_cphttptools.py (modified) (3 diffs)
- branches/cherrypy-2.x/cherrypy/filters/cachefilter.py (modified) (2 diffs)
- branches/cherrypy-2.x/cherrypy/test/test_cache_filter.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/cherrypy-2.x/cherrypy/_cphttptools.py
r1504 r1506 4 4 import os 5 5 import sys 6 import time 6 7 import types 7 8 … … 365 366 self.header_list = None 366 367 self.body = None 368 self.time = time.time() 367 369 368 370 self.headers = httptools.HeaderMap() … … 372 374 "Content-Type": content_type, 373 375 "Server": "CherryPy/" + cherrypy.__version__, 374 "Date": httptools.HTTPDate( ),376 "Date": httptools.HTTPDate(time.gmtime(self.time)), 375 377 "Set-Cookie": [], 376 378 "Content-Length": None branches/cherrypy-2.x/cherrypy/filters/cachefilter.py
r1494 r1506 1 1 import datetime 2 import Queue 2 3 import threading 3 import Queue4 4 import time 5 5 6 6 import cherrypy 7 from cherrypy.lib import httptools 7 8 import basefilter 8 9 … … 212 213 yield "Total non-modified content: %d\n" % cache.totNonModified 213 214 index.exposed = True 215 216 217 def expires(secs=0, force=False): 218 """Tool for influencing cache mechanisms using the 'Expires' header. 219 220 'secs' must be either an int or a datetime.timedelta, and indicates the 221 number of seconds between response.time and when the response should 222 expire. The 'Expires' header will be set to (response.time + secs). 223 224 If 'secs' is zero, the following "cache prevention" headers are also set: 225 'Pragma': 'no-cache' 226 'Cache-Control': 'no-cache' 227 228 If 'force' is False (the default), the following headers are checked: 229 'Etag', 'Last-Modified', 'Age', 'Expires'. If any are already present, 230 none of the above response headers are set. 231 """ 232 233 response = cherrypy.response 234 235 cacheable = False 236 if not force: 237 # some header names that indicate that the response can be cached 238 for indicator in ('Etag', 'Last-Modified', 'Age', 'Expires'): 239 if indicator in response.headers: 240 cacheable = True 241 break 242 243 if not cacheable: 244 if isinstance(secs, datetime.timedelta): 245 secs = (86400 * secs.days) + secs.seconds 246 247 if secs == 0: 248 if force or ("Pragma" not in response.headers): 249 response.headers["Pragma"] = "no-cache" 250 if cherrypy.response.version >= "1.1": 251 if force or ("Cache-Control" not in response.headers): 252 response.headers["Cache-Control"] = "no-cache" 253 254 expiry = httptools.HTTPDate(time.gmtime(response.time + secs)) 255 if force or ("Expires" not in response.headers): 256 response.headers["Expires"] = expiry branches/cherrypy-2.x/cherrypy/test/test_cache_filter.py
r1494 r1506 3 3 4 4 import cherrypy 5 import time 5 from cherrypy.filters.cachefilter import expires 6 6 7 7 … … 16 16 return msg 17 17 index.exposed = True 18 18 19 class UnCached(object): 20 21 use_force = False 22 23 def force(self): 24 self.use_force = True 25 expires(force=self.use_force) 26 return "being forceful" 27 force.exposed = True 28 29 def dynamic(self): 30 cherrypy.response.headers['Cache-Control'] = 'private' 31 expires(force=self.use_force) 32 return "D-d-d-dynamic!" 33 dynamic.exposed = True 34 35 def cacheable(self): 36 cherrypy.response.headers['Etag'] = 'bibbitybobbityboo' 37 expires(force=self.use_force) 38 return "Hi, I'm cacheable." 39 cacheable.exposed = True 40 41 def specific(self): 42 expires(secs=86400, force=self.use_force) 43 return "I am being specific" 44 specific.exposed = True 45 19 46 cherrypy.root = Root() 47 cherrypy.root.expires = UnCached() 20 48 cherrypy.config.update({ 21 'server.log_to_screen': False, 22 'server.environment': 'production', 23 'cache_filter.on': True, 49 'global': {'server.log_to_screen': False, 50 'server.environment': 'production', 51 'cache_filter.on': True, 52 }, 53 '/expires': {'cache_filter.on': False}, 24 54 }) 25 55 … … 51 81 self.getPage("/", method="GET") 52 82 self.assertBody('visit #5') 83 84 def testExpiresTool(self): 85 86 # test setting an expires header 87 self.getPage("/expires/specific") 88 self.assertStatus("200 OK") 89 self.assertHeader("Expires") 90 91 # dynamic content that sets indicators should not have 92 # "cache prevention" headers 93 self.getPage("/expires/cacheable") 94 self.assertStatus("200 OK") 95 self.assertNoHeader("Pragma") 96 self.assertNoHeader("Cache-Control") 97 98 self.getPage('/expires/dynamic') 99 self.assertBody("D-d-d-dynamic!") 100 # the Cache-Control header should be untouched 101 self.assertHeader("Cache-Control", "private") 102 103 # configure the tool to ignore indicators and replace existing headers 104 self.getPage("/expires/force") 105 self.assertStatus("200 OK") 106 # This also gives us a chance to test 0 expiry with no other headers 107 self.assertHeader("Pragma", "no-cache") 108 conf = cherrypy.config.get 109 if conf('server.protocol_version', '') == "HTTP/1.1": 110 self.assertHeader("Cache-Control", "no-cache") 111 d = self.assertHeader("Date") 112 self.assertHeader("Expires", d) 113 114 # the cacheable handler should now have "cache prevention" headers 115 self.getPage("/expires/cacheable") 116 self.assertStatus("200 OK") 117 self.assertHeader("Pragma", "no-cache") 118 if conf('server.protocol_version', '') == "HTTP/1.1": 119 self.assertHeader("Cache-Control", "no-cache") 120 d = self.assertHeader("Date") 121 self.assertHeader("Expires", d) 122 123 self.getPage('/expires/dynamic') 124 self.assertBody("D-d-d-dynamic!") 125 # dynamic sets Cache-Control to private but it should be 126 # overwritten here ... 127 self.assertHeader("Pragma", "no-cache") 128 if conf('server.protocol_version', '') == "HTTP/1.1": 129 self.assertHeader("Cache-Control", "no-cache") 130 d = self.assertHeader("Date") 131 self.assertHeader("Expires", d) 53 132 54 133

