Changeset 1117
- Timestamp:
- 06/03/06 00:42:24
- Files:
-
- trunk/cherrypy/lib/caching.py (modified) (2 diffs)
- trunk/cherrypy/lib/cptools.py (modified) (2 diffs)
- trunk/cherrypy/lib/static.py (modified) (2 diffs)
- trunk/cherrypy/test/test.py (modified) (2 diffs)
- trunk/cherrypy/test/test_etags.py (added)
- trunk/cherrypy/test/test_static.py (modified) (1 diff)
- trunk/cherrypy/tools.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/lib/caching.py
r1102 r1117 4 4 5 5 import cherrypy 6 from cherrypy.lib import cptools 6 7 7 8 … … 105 106 if c: 106 107 expirationTime, lastModified, obj = cacheData 107 s, h, b = obj 108 modifiedSince = cherrypy.request.headers.get('If-Modified-Since', None) 109 if modifiedSince is not None and modifiedSince == lastModified: 110 cherrypy._cache.totNonModified += 1 111 cherrypy.response.status = "304 Not Modified" 112 ct = h.get("Content-Type") 113 if ct: 114 cherrypy.response.header_list["Content-Type"] = ct 115 cherrypy.response.body = None 116 else: 117 # serve it & get out from the request 118 cherrypy.response.status, cherrypy.response.header_list, body = s, h, b 119 cherrypy.response.body = body 108 s, cherrypy.response.header_list, b = obj 109 try: 110 cptools.validate_since() 111 except cherrypy.HTTPError, x: 112 if x.status == 304: 113 cherrypy._cache.totNonModified += 1 114 raise 115 116 # serve it & get out from the request 117 cherrypy.response.status = s 118 cherrypy.response.body = b 120 119 return c 121 120 trunk/cherrypy/lib/cptools.py
r1106 r1117 2 2 3 3 import inspect 4 import md5 4 5 import os 5 6 import sys … … 178 179 179 180 180 # Tool code 181 # Conditional HTTP request support # 182 183 def validate_etags(autotags=False): 184 """Validate the current ETag against If-Match, If-None-Match headers.""" 185 # Guard against being run twice. 186 if hasattr(cherrypy.response, "ETag"): 187 return 188 189 etag = cherrypy.response.headers.get('ETag') 190 191 if (not etag) and autotags: 192 etag = '"%s"' % md5.new(cherrypy.response.collapse_body()).hexdigest() 193 cherrypy.response.headers['ETag'] = etag 194 195 if etag: 196 cherrypy.response.ETag = etag 197 198 status, reason, msg = httptools.validStatus(cherrypy.response.status) 199 200 conditions = cherrypy.request.headers.elements('If-Match') or [] 201 conditions = [str(x) for x in conditions] 202 if conditions and not (conditions == ["*"] or etag in conditions): 203 if (status >= 200 and status < 299) or status == 412: 204 raise cherrypy.HTTPError(412) 205 206 conditions = cherrypy.request.headers.elements('If-None-Match') or [] 207 conditions = [str(x) for x in conditions] 208 if conditions == ["*"] or etag in conditions: 209 if (status >= 200 and status < 299) or status == 304: 210 if cherrypy.request.method in ("GET", "HEAD"): 211 raise cherrypy.HTTPRedirect([], 304) 212 else: 213 raise cherrypy.HTTPError(412) 214 215 def validate_since(): 216 """Validate the current Last-Modified against If-Modified-Since headers.""" 217 lastmod = cherrypy.response.headers.get('Last-Modified') 218 if lastmod: 219 status, reason, msg = httptools.validStatus(cherrypy.response.status) 220 221 since = cherrypy.request.headers.get('If-Unmodified-Since') 222 if since and since != lastmod: 223 if (status >= 200 and status < 299) or status == 412: 224 raise cherrypy.HTTPError(412) 225 226 since = cherrypy.request.headers.get('If-Modified-Since') 227 if since and since == lastmod: 228 if (status >= 200 and status < 299) or status == 304: 229 if cherrypy.request.method in ("GET", "HEAD"): 230 raise cherrypy.HTTPRedirect([], 304) 231 else: 232 raise cherrypy.HTTPError(412) 233 234 235 # Tool code # 181 236 182 237 def base_url(base=None, use_x_forwarded_host=True): trunk/cherrypy/lib/static.py
r1096 r1117 11 11 12 12 import cherrypy 13 from cherrypy.lib import httptools 14 15 16 def modified_since(path, stat=None): 17 """Check whether a file has been modified since the date 18 provided in 'If-Modified-Since' 19 It doesn't check if the file exists or not 20 Return True if has been modified, False otherwise 21 """ 22 # serve_file already creates a stat object so let's not 23 # waste our energy to do it again 24 if not stat: 25 try: 26 stat = os.stat(path) 27 except OSError: 28 if cherrypy.config.get('log_file_not_found', False): 29 cherrypy.log(" NOT FOUND file: %s" % path, "DEBUG") 30 raise cherrypy.NotFound() 31 32 response = cherrypy.response 33 strModifTime = httptools.HTTPDate(time.gmtime(stat.st_mtime)) 34 if cherrypy.request.headers.has_key('If-Modified-Since'): 35 if cherrypy.request.headers['If-Modified-Since'] == strModifTime: 36 return False 37 response.headers['Last-Modified'] = strModifTime 38 return True 13 from cherrypy.lib import cptools, httptools 39 14 40 15 … … 81 56 response.headers['Content-Type'] = contentType 82 57 83 if not modified_since(path, stat): 84 response.status = "304 Not Modified" 85 response.body = [] 86 if getattr(cherrypy, "debug", None): 87 cherrypy.log(" Found file (304 Not Modified): %s" % path, "DEBUG") 88 return [] 58 # Set the Last-Modified response header, so that 59 # modified-since validation code can work. 60 response.headers['Last-Modified'] = httptools.HTTPDate(time.gmtime(stat.st_mtime)) 61 cptools.validate_since() 89 62 90 63 if disposition is not None: trunk/cherrypy/test/test.py
r1114 r1117 87 87 self.protocol = "HTTP/1.1" 88 88 89 longopts = ['cover', 'profile', '1. 1', 'help', 'basedir=', 'port=',89 longopts = ['cover', 'profile', '1.0', 'help', 'basedir=', 'port=', 90 90 'server='] 91 91 longopts.extend(self.available_servers) … … 295 295 'test_tools', 296 296 'test_decodingencoding', 297 'test_etags', 297 298 'test_gzip', 298 299 'test_objectmapping', trunk/cherrypy/test/test_static.py
r1114 r1117 128 128 ims = ("If-Modified-Since", lastmod) 129 129 self.getPage("/static/dirback.jpg", headers=[ims]) 130 self.assertStatus("304 Not Modified")130 self.assertStatus("304 Not modified") 131 131 ## 132 132 ## # Test lots of requests for the same file (no If-Mod). trunk/cherrypy/tools.py
r1115 r1117 228 228 # because it's failsafe and the redirect would be swallowed. 229 229 virtual_host = Tool('before_request_body', cptools.virtual_host) 230 log_tracebacks = Tool('before_error_response', cptools.log_traceback )231 log_headers = Tool('before_error_response', cptools.log_request_headers )230 log_tracebacks = Tool('before_error_response', cptools.log_traceback, 'log_tracebacks') 231 log_headers = Tool('before_error_response', cptools.log_request_headers, 'log_headers') 232 232 err_redirect = ErrorTool(cptools.redirect, 'err_redirect') 233 etags = Tool('before_finalize', cptools.validate_etags, 'etags') 233 234 del cptools 234 235

