Changeset 1941
- Timestamp:
- 04/05/08 15:40:13
- Files:
-
- branches/800-error-handlers/cherrypy/_cperror.py (modified) (3 diffs)
- branches/800-error-handlers/cherrypy/_cprequest.py (modified) (4 diffs)
- branches/800-error-handlers/cherrypy/test/test_core.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/800-error-handlers/cherrypy/_cperror.py
r1839 r1941 149 149 150 150 151 def clean_headers(status): 152 """Remove any headers which should not apply to an error response.""" 153 import cherrypy 154 155 response = cherrypy.response 156 157 # Remove headers which applied to the original content, 158 # but do not apply to the error page. 159 respheaders = response.headers 160 for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After", 161 "Vary", "Content-Encoding", "Content-Length", "Expires", 162 "Content-Location", "Content-MD5", "Last-Modified"]: 163 if respheaders.has_key(key): 164 del respheaders[key] 165 166 if status != 416: 167 # A server sending a response with status code 416 (Requested 168 # range not satisfiable) SHOULD include a Content-Range field 169 # with a byte-range-resp-spec of "*". The instance-length 170 # specifies the current length of the selected resource. 171 # A response with status code 206 (Partial Content) MUST NOT 172 # include a Content-Range field with a byte-range- resp-spec of "*". 173 if respheaders.has_key("Content-Range"): 174 del respheaders["Content-Range"] 175 176 151 177 class HTTPError(CherryPyException): 152 178 """ Exception used to return an HTTP error code (4xx-5xx) to the client. … … 174 200 response = cherrypy.response 175 201 176 # Remove headers which applied to the original content, 177 # but do not apply to the error page. 178 respheaders = response.headers 179 for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After", 180 "Vary", "Content-Encoding", "Content-Length", "Expires", 181 "Content-Location", "Content-MD5", "Last-Modified"]: 182 if respheaders.has_key(key): 183 del respheaders[key] 184 185 if self.status != 416: 186 # A server sending a response with status code 416 (Requested 187 # range not satisfiable) SHOULD include a Content-Range field 188 # with a byte-range-resp-spec of "*". The instance-length 189 # specifies the current length of the selected resource. 190 # A response with status code 206 (Partial Content) MUST NOT 191 # include a Content-Range field with a byte-range- resp-spec of "*". 192 if respheaders.has_key("Content-Range"): 193 del respheaders["Content-Range"] 202 clean_headers(self.status) 194 203 195 204 # In all cases, finalize will be called after this method, … … 199 208 if cherrypy.request.show_tracebacks: 200 209 tb = format_exc() 201 resp headers['Content-Type'] = "text/html"210 response.headers['Content-Type'] = "text/html" 202 211 203 212 content = self.get_error_page(self.status, traceback=tb, 204 213 message=self.message) 205 214 response.body = content 206 resp headers['Content-Length'] = len(content)215 response.headers['Content-Length'] = len(content) 207 216 208 217 _be_ie_unfriendly(self.status) branches/800-error-handlers/cherrypy/_cprequest.py
r1938 r1941 393 393 error_page = {} 394 394 error_page__doc = """ 395 A dict of {error code: response filename} pairs. The named response 396 files should be Python string-formatting templates, and can expect by 397 default to receive the format values with the mapping keys 'status', 398 'message', 'traceback', and 'version'. The set of format mappings 399 can be extended by overriding HTTPError.set_response.""" 395 A dict of {error code: response filename or callable} pairs. 396 The named response files should be Python string-formatting templates, 397 and can expect by default to receive format values with the mapping 398 keys 'status', 'message', 'traceback', and 'version'. The set of 399 format mappings can be extended by overriding HTTPError.set_response. 400 401 If a callable is provided, it will be called with the HTTPError 402 instance as the only argument. The callable is expected to set 403 response.status, .headers and .body appropriately. 404 405 If no entry is given for an error code, the HTTPError's set_response 406 method will handle the error (by setting .status, .headers, and .body). 407 """ 400 408 401 409 show_tracebacks = True … … 592 600 cherrypy.response.finalize() 593 601 except (cherrypy.HTTPRedirect, cherrypy.HTTPError), inst: 594 inst.set_response() 602 ep = self.error_page.get(inst.status, '') 603 if ep and callable(ep): 604 ep(inst) 605 else: 606 inst.set_response() 595 607 self.stage = 'before_finalize (HTTPError)' 596 608 self.hooks.run('before_finalize') … … 716 728 717 729 def handle_error(self, exc): 718 """Handle the last exception. (Core)"""730 """Handle the last unanticipated exception. (Core)""" 719 731 try: 720 732 self.hooks.run("before_error_response") … … 724 736 cherrypy.response.finalize() 725 737 except cherrypy.HTTPRedirect, inst: 726 inst.set_response() 738 ep = self.error_page.get(inst.status, '') 739 if ep and callable(ep): 740 ep(inst) 741 else: 742 inst.set_response() 727 743 cherrypy.response.finalize() 728 744 branches/800-error-handlers/cherrypy/test/test_core.py
r1921 r1941 240 240 for chunk in self.as_yield(): 241 241 yield chunk 242 243 242 243 244 def page401(e): 245 cherrypy.response.status = e.status 246 cherrypy._cperror.clean_headers(e.status) 247 cherrypy.response.body = "Well, I'm very sorry but you haven't paid!" 248 249 244 250 class Error(Test): 245 251 … … 247 253 } 248 254 249 def custom(self): 250 raise cherrypy.HTTPError(404, "No, <b>really</b>, not found!") 251 custom._cp_config = {'error_page.404': os.path.join(localDir, "static/index.html")} 255 def custom(self, err='404'): 256 raise cherrypy.HTTPError(int(err), "No, <b>really</b>, not found!") 257 custom._cp_config = {'error_page.404': os.path.join(localDir, "static/index.html"), 258 'error_page.401': page401, 259 } 252 260 253 261 def noexist(self): … … 725 733 self.assertStatus(404) 726 734 self.assertBody("Hello, world\r\n" + (" " * 499)) 735 736 # Test custom error page. 737 self.getPage("/error/custom?err=401") 738 self.assertStatus(401) 739 self.assertBody("Well, I'm very sorry but you haven't paid!") 727 740 728 741 # Test error in custom error page (ticket #305).

