Changeset 1082
- Timestamp:
- 05/01/06 01:40:59
- Files:
-
- trunk/cherrypy/__init__.py (modified) (1 diff)
- trunk/cherrypy/_cperror.py (modified) (7 diffs)
- trunk/cherrypy/_cprequest.py (modified) (13 diffs)
- trunk/cherrypy/_cputil.py (modified) (5 diffs)
- trunk/cherrypy/_cpwsgi.py (modified) (4 diffs)
- trunk/cherrypy/config.py (modified) (2 diffs)
- trunk/cherrypy/lib/cptools.py (modified) (2 diffs)
- trunk/cherrypy/lib/httptools.py (modified) (1 diff)
- trunk/cherrypy/lib/sessions.py (modified) (1 diff)
- trunk/cherrypy/lib/wsgiapp.py (modified) (1 diff)
- trunk/cherrypy/lib/xmlrpc.py (modified) (1 diff)
- trunk/cherrypy/test/benchmark.py (modified) (1 diff)
- trunk/cherrypy/test/helper.py (modified) (1 diff)
- trunk/cherrypy/test/test_config.py (modified) (1 diff)
- trunk/cherrypy/test/test_core.py (modified) (6 diffs)
- trunk/cherrypy/test/test_custom_filters.py (modified) (1 diff)
- trunk/cherrypy/test/test_virtualhost_filter.py (modified) (1 diff)
- trunk/cherrypy/tools.py (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/__init__.py
r1072 r1082 86 86 # Load _cputil lazily to avoid circular references, and 87 87 # to allow profiler and coverage tools to work on it. 88 import _cputil 88 import _cputil, _cperror 89 89 logfunc = _cputil.get_special_attribute('_cp_log_message') 90 90 91 91 if traceback: 92 msg += _cp util.formatExc()92 msg += _cperror.format_exc() 93 93 94 94 logfunc(msg, context, severity) trunk/cherrypy/_cperror.py
r1072 r1082 1 1 """Error classes for CherryPy.""" 2 2 3 import cgi 4 import sys 5 import traceback 3 6 import urllib 7 import urlparse 8 9 from cherrypy.lib import httptools 10 4 11 5 12 class Error(Exception): … … 14 21 pass 15 22 16 class RequestHandled(Exception):17 """Exception raised when no further request handling should occur."""18 pass19 20 23 class InternalRedirect(Exception): 21 24 """Exception raised when processing should be handled by a different path. … … 31 34 def __init__(self, path, params=None): 32 35 import cherrypy 33 import cgi34 36 request = cherrypy.request 35 37 … … 48 50 else: 49 51 request.query_string = urllib.urlencode(params) 50 request.queryString = request.query_string51 52 request.params = params.copy() 52 53 … … 65 66 66 67 def __init__(self, urls, status=None): 67 import urlparse68 68 import cherrypy 69 69 … … 152 152 153 153 def set_response(self): 154 """Set cherrypy.response status, headers, and body.""" 154 155 import cherrypy 155 handler = cherrypy._cputil.get_special_attribute("_cp_on_http_error") 156 handler(self.status, self.message) 156 157 response = cherrypy.response 158 159 # Remove headers which applied to the original content, 160 # but do not apply to the error page. 161 for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After", 162 "Vary", "Content-Encoding", "Content-Length", "Expires", 163 "Content-Location", "Content-MD5", "Last-Modified"]: 164 if response.headers.has_key(key): 165 del response.headers[key] 166 167 if self.status != 416: 168 # A server sending a response with status code 416 (Requested 169 # range not satisfiable) SHOULD include a Content-Range field 170 # with a byte-range- resp-spec of "*". The instance-length 171 # specifies the current length of the selected resource. 172 # A response with status code 206 (Partial Content) MUST NOT 173 # include a Content-Range field with a byte-range- resp-spec of "*". 174 if response.headers.has_key("Content-Range"): 175 del response.headers["Content-Range"] 176 177 # In all cases, finalize will be called after this method, 178 # so don't bother cleaning up response values here. 179 response.status = self.status 180 tb = None 181 if cherrypy.config.get('server.show_tracebacks', False): 182 tb = format_exc() 183 content = get_error_page(self.status, traceback=tb, 184 message=self.message) 185 response.body = content 186 response.headers['Content-Length'] = len(content) 187 response.headers['Content-Type'] = "text/html" 188 189 be_ie_unfriendly(self.status) 157 190 158 191 … … 168 201 169 202 170 class InternalError(HTTPError): 171 """ Error that should never happen """ 172 173 def __init__(self, message=None): 174 HTTPError.__init__(self, 500, message) 175 203 _HTTPErrorTemplate = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 204 <html> 205 <head> 206 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> 207 <title>%(status)s</title> 208 <style type="text/css"> 209 #powered_by { 210 margin-top: 20px; 211 border-top: 2px solid black; 212 font-style: italic; 213 } 214 215 #traceback { 216 color: red; 217 } 218 </style> 219 </head> 220 <body> 221 <h2>%(status)s</h2> 222 <p>%(message)s</p> 223 <pre id="traceback">%(traceback)s</pre> 224 <div id="powered_by"> 225 <span>Powered by <a href="http://www.cherrypy.org">CherryPy %(version)s</a></span> 226 </div> 227 </body> 228 </html> 229 ''' 230 231 def get_error_page(status, **kwargs): 232 """Return an HTML page, containing a pretty error response. 233 234 status should be an int or a str. 235 kwargs will be interpolated into the page template. 236 """ 237 import cherrypy 238 239 try: 240 code, reason, message = httptools.validStatus(status) 241 except ValueError, x: 242 raise cherrypy.HTTPError(500, x.args[0]) 243 244 # We can't use setdefault here, because some 245 # callers send None for kwarg values. 246 if kwargs.get('status') is None: 247 kwargs['status'] = "%s %s" % (code, reason) 248 if kwargs.get('message') is None: 249 kwargs['message'] = message 250 if kwargs.get('traceback') is None: 251 kwargs['traceback'] = '' 252 if kwargs.get('version') is None: 253 kwargs['version'] = cherrypy.__version__ 254 for k, v in kwargs.iteritems(): 255 if v is None: 256 kwargs[k] = "" 257 else: 258 kwargs[k] = cgi.escape(kwargs[k]) 259 260 template = _HTTPErrorTemplate 261 error_page_file = cherrypy.config.get('error_page.%s' % code, '') 262 if error_page_file: 263 try: 264 template = file(error_page_file, 'rb').read() 265 except: 266 m = kwargs['message'] 267 if m: 268 m += "<br />" 269 m += ("In addition, the custom error page " 270 "failed:\n<br />%s" % (sys.exc_info()[1])) 271 kwargs['message'] = m 272 273 return template % kwargs 274 275 276 _ie_friendly_error_sizes = { 277 400: 512, 403: 256, 404: 512, 405: 256, 278 406: 512, 408: 512, 409: 512, 410: 256, 279 500: 512, 501: 512, 505: 512, 280 } 281 282 283 def be_ie_unfriendly(status): 284 import cherrypy 285 response = cherrypy.response 286 287 # For some statuses, Internet Explorer 5+ shows "friendly error 288 # messages" instead of our response.body if the body is smaller 289 # than a given size. Fix this by returning a body over that size 290 # (by adding whitespace). 291 # See http://support.microsoft.com/kb/q218155/ 292 s = _ie_friendly_error_sizes.get(status, 0) 293 if s: 294 s += 1 295 # Since we are issuing an HTTP error status, we assume that 296 # the entity is short, and we should just collapse it. 297 content = response.collapse_body() 298 l = len(content) 299 if l and l < s: 300 # IN ADDITION: the response must be written to IE 301 # in one chunk or it will still get replaced! Bah. 302 content = content + (" " * (s - l)) 303 response.body = content 304 response.headers['Content-Length'] = len(content) 305 306 307 def format_exc(exc=None): 308 """format_exc(exc=None) -> exc (or sys.exc_info if None), formatted.""" 309 if exc is None: 310 exc = sys.exc_info() 311 if exc == (None, None, None): 312 return "" 313 return "".join(traceback.format_exception(*exc)) 314 315 def bare_error(extrabody=None): 316 """Produce status, headers, body for a critical error. 317 318 Returns a triple without calling any other questionable functions, 319 so it should be as error-free as possible. Call it from an HTTP server 320 if you get errors outside of the request. 321 322 If extrabody is None, a friendly but rather unhelpful error message 323 is set in the body. If extrabody is a string, it will be appended 324 as-is to the body. 325 """ 326 327 # The whole point of this function is to be a last line-of-defense 328 # in handling errors. That is, it must not raise any errors itself; 329 # it cannot be allowed to fail. Therefore, don't add to it! 330 # In particular, don't call any other CP functions. 331 332 body = "Unrecoverable error in the server." 333 if extrabody is not None: 334 body += "\n" + extrabody 335 336 return ("500 Internal Server Error", 337 [('Content-Type', 'text/plain'), 338 ('Content-Length', str(len(body)))], 339 [body]) 340 trunk/cherrypy/_cprequest.py
r1080 r1082 7 7 8 8 import cherrypy 9 from cherrypy import _cp util, _cpcgifs, tools9 from cherrypy import _cperror, _cputil, _cpcgifs, tools 10 10 from cherrypy.lib import cptools, httptools 11 11 … … 22 22 scheme should be a string, either "http" or "https". 23 23 """ 24 self.remote_addr = remote_addr25 self.remote_port = remote_port26 self.remote_host = remote_host24 self.remote_addr = remote_addr 25 self.remote_port = remote_port 26 self.remote_host = remote_host 27 27 28 28 self.scheme = scheme … … 43 43 cherrypy.serving.__dict__.clear() 44 44 45 def run(self, request Line, headers, rfile):45 def run(self, request_line, headers, rfile): 46 46 """Process the Request. 47 47 48 request Line should be of the form "GET /path HTTP/1.0".48 request_line should be of the form "GET /path HTTP/1.0". 49 49 headers should be a list of (name, value) tuples. 50 50 rfile should be a file-like object containing the HTTP request … … 60 60 61 61 """ 62 self.requestLine = requestLine.strip() 62 self.log_access = _cputil.log_access 63 self.error_response = cherrypy.HTTPError(500).set_response 64 65 self.request_line = request_line.strip() 63 66 self.header_list = list(headers) 64 67 self.rfile = rfile 65 66 68 self.headers = httptools.HeaderMap() 67 69 self.simple_cookie = Cookie.SimpleCookie() … … 76 78 cherrypy.response.body = [] 77 79 78 _cputil.get_special_attribute("_cp_log_access")()80 self.log_access() 79 81 80 82 return cherrypy.response 81 83 82 84 def _run(self): 85 conf = cherrypy.config.get 83 86 84 87 try: … … 86 89 # because request.object_path is used for config lookups 87 90 # right away. 88 self.process RequestLine()89 self.dispatch = c herrypy.config.get("dispatch") or _cputil.dispatch91 self.process_request_line() 92 self.dispatch = conf("dispatch") or _cputil.dispatch 90 93 self.hooks.setup() 91 94 … … 94 97 95 98 try: 96 self.process Headers()99 self.process_headers() 97 100 98 101 self.hooks.run('before_request_body') 99 if self.process RequestBody:100 self.process Body()102 if self.process_request_body: 103 self.process_body() 101 104 102 105 # Loop to allow for InternalRedirect. … … 112 115 self.hooks.run('before_finalize') 113 116 cherrypy.response.finalize() 114 except cherrypy.RequestHandled:115 pass116 117 except (cherrypy.HTTPRedirect, cherrypy.HTTPError), inst: 117 118 # For an HTTPRedirect or HTTPError (including NotFound), … … 126 127 raise 127 128 except: 128 if c herrypy.config.get("server.throw_errors", False):129 if conf("server.throw_errors", False): 129 130 raise 130 cherrypy.response.handleError(sys.exc_info()) 131 132 def processRequestLine(self): 133 rl = self.requestLine 134 method, path, qs, proto = httptools.parseRequestLine(rl) 131 self.handle_error(sys.exc_info()) 132 133 def process_request_line(self): 134 """Parse the first line (e.g. "GET /path HTTP/1.1") of the request.""" 135 rl = self.request_line 136 method, path, qs, proto = httptools.parse_request_line(rl) 135 137 if path == "*": 136 138 path = "global" 137 139 138 140 self.method = method 139 self.process RequestBody = method in ("POST", "PUT")141 self.process_request_body = method in ("POST", "PUT") 140 142 141 143 self.path = path … … 169 171 cherrypy.response.version = min(self.version, server_v) 170 172 171 def process Headers(self):173 def process_headers(self): 172 174 self.params = httptools.parseQueryString(self.query_string) 173 175 … … 202 204 doc="The URL as entered in a browser (read-only).") 203 205 204 def processBody(self): 206 def process_body(self): 207 """Convert request.rfile into request.params (or request.body).""" 205 208 # Create a copy of headers with lowercase keys because 206 209 # FieldStorage doesn't work otherwise … … 225 228 else: 226 229 self.params.update(httptools.paramsFromCGIForm(forms)) 230 231 def handle_error(self, exc): 232 response = cherrypy.response 233 try: 234 self.hooks.run("before_error_response") 235 if self.error_response: 236 self.error_response() 237 self.hooks.run("after_error_response") 238 response.finalize() 239 return 240 except cherrypy.HTTPRedirect, inst: 241 try: 242 inst.set_response() 243 response.finalize() 244 return 245 except (KeyboardInterrupt, SystemExit): 246 raise 247 except: 248 # Fall through to the second error handler 249 pass 250 except (KeyboardInterrupt, SystemExit): 251 raise 252 except: 253 # Fall through to the second error handler 254 pass 255 256 # Failure in error handler or finalize. Bypass them. 257 if cherrypy.config.get('server.show_tracebacks', False): 258 dbltrace = ("\n===First Error===\n\n%s" 259 "\n\n===Second Error===\n\n%s\n\n") 260 body = dbltrace % (_cperror.format_exc(exc), 261 _cperror.format_exc()) 262 else: 263 body = "" 264 r = _cperror.bare_error(body) 265 response.status, response.header_list, response.body = r 227 266 228 267 … … 325 364 name, value = line.split(": ", 1) 326 365 self.header_list.append((name, value)) 327 328 dbltrace = "\n===First Error===\n\n%s\n\n===Second Error===\n\n%s\n\n"329 330 def handleError(self, exc):331 """Set status, headers, and body when an unanticipated error occurs."""332 try:333 cherrypy.request.hooks.run('before_error_response')334 335 _cputil.get_special_attribute('_cp_on_error')()336 self.finalize()337 338 cherrypy.request.hooks.run('after_error_response')339 return340 except cherrypy.HTTPRedirect, inst:341 try:342 inst.set_response()343 self.finalize()344 return345 except (KeyboardInterrupt, SystemExit):346 raise347 except:348 # Fall through to the second error handler349 pass350 except (KeyboardInterrupt, SystemExit):351 raise352 except:353 # Fall through to the second error handler354 pass355 356 # Failure in error hooks or finalize.357 # Bypass them all.358 if cherrypy.config.get('server.show_tracebacks', False):359 body = self.dbltrace % (_cputil.formatExc(exc),360 _cputil.formatExc())361 else:362 body = ""363 self.setBareError(body)364 365 def setBareError(self, body=None):366 self.status, self.header_list, self.body = _cputil.bareError(body)367 trunk/cherrypy/_cputil.py
r1080 r1082 117 117 def get_special_attribute(name): 118 118 """Return the special attribute. A special attribute is one that 119 applies to all of the children from where it is defined, such as 120 _cp_on_error.""" 119 applies to all of the children from where it is defined.""" 121 120 122 121 # First, we look in the right-most object to see if this special … … 153 152 _cpGlobalHandler.exposed = True 154 153 154 155 155 def logtime(): 156 156 now = datetime.datetime.now() … … 159 159 now.day, month, now.year, now.hour, now.minute, now.second) 160 160 161 def _cp_log_access():161 def log_access(): 162 162 """Default method for logging access""" 163 request = cherrypy.request 163 164 164 165 tmpl = '%(h)s %(l)s %(u)s [%(t)s] "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' 165 s = tmpl % {'h': cherrypy.request.remote_host,166 s = tmpl % {'h': request.remote_host, 166 167 'l': '-', 167 'u': getattr( cherrypy.request, "login", None) or "-",168 'u': getattr(request, "login", None) or "-", 168 169 't': logtime(), 169 'r': cherrypy.request.requestLine,170 'r': request.request_line, 170 171 's': cherrypy.response.status.split(" ", 1)[0], 171 172 'b': cherrypy.response.headers.get('Content-Length', '') or "-", 172 'f': cherrypy.request.headers.get('referer', ''),173 'a': cherrypy.request.headers.get('user-agent', ''),173 'f': request.headers.get('referer', ''), 174 'a': request.headers.get('user-agent', ''), 174 175 } 175 176 … … 182 183 f.write(s + '\n') 183 184 f.close() 184 185 185 186 186 _log_severity_levels = {0: "INFO", 1: "WARNING", 2: "ERROR"} … … 209 209 f.close() 210 210 211 212 _HTTPErrorTemplate = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">213 <html>214 <head>215 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>216 <title>%(status)s</title>217 <style type="text/css">218 #powered_by {219 margin-top: 20px;220 border-top: 2px solid black;221 font-style: italic;222 }223 224 #traceback {225 color: red;226 }227 </style>228 </head>229 <body>230 <h2>%(status)s</h2>231 <p>%(message)s</p>232 <pre id="traceback">%(traceback)s</pre>233 <div id="powered_by">234 <span>Powered by <a href="http://www.cherrypy.org">CherryPy %(version)s</a></span>235 </div>236 </body>237 </html>238 '''239 240 def getErrorPage(status, **kwargs):241 """Return an HTML page, containing a pretty error response.242 243 status should be an int or a str.244 kwargs will be interpolated into the page template.245 """246 247 try:248 code, reason, message = httptools.validStatus(status)249 except ValueError, x:250 raise cherrypy.HTTPError(500, x.args[0])251 252 # We can't use setdefault here, because some253 # callers send None for kwarg values.254 if kwargs.get('status') is None:255 kwargs['status'] = "%s %s" % (code, reason)256 if kwargs.get('message') is None:257 kwargs['message'] = message258 if kwargs.get('traceback') is None:259 kwargs['traceback'] = ''260 if kwargs.get('version') is None:261 kwargs['version'] = cherrypy.__version__262 for k, v in kwargs.iteritems():263 if v is None:264 kwargs[k] = ""265 else:266 kwargs[k] = cgi.escape(kwargs[k])267 268 template = _HTTPErrorTemplate269 error_page_file = cherrypy.config.get('error_page.%s' % code, '')270 if error_page_file:271 try:272 template = file(error_page_file, 'rb').read()273 except:274 m = kwargs['message']275 if m:276 m += "<br />"277 m += ("In addition, the custom error page "278 "failed:\n<br />%s" % (sys.exc_info()[1]))279 kwargs['message'] = m280 281 return template % kwargs282 283 def _cp_on_error():284 """ Default _cp_on_error method """285 # Allow logging of only *unexpected* HTTPError's.286 if (not cherrypy.config.get('server.log_tracebacks', True)287 and cherrypy.config.get('server.log_unhandled_tracebacks', True)):288 cherrypy.log(traceback=True)289 cherrypy.HTTPError(500).set_response()290 291 def _cp_on_http_error(status, message):292 """Default _cp_on_http_error method.293 294 status should be an int.295 """296 tb = formatExc()297 logmsg = ""298 299 if cherrypy.config.get('server.log_tracebacks', True):300 logmsg = tb301 if cherrypy.config.get('server.log_request_headers', True):302 h = [" %s: %s" % (k, v) for k, v in cherrypy.request.header_list]303 logmsg += 'Request Headers:\n' + '\n'.join(h)304 if logmsg:305 cherrypy.log(logmsg, "HTTP")306 307 if not cherrypy.config.get('server.show_tracebacks', False):308 tb = None309 310 response = cherrypy.response311 312 # Remove headers which applied to the original content,313 # but do not apply to the error page.314 for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After",315 "Vary", "Content-Encoding", "Content-Length", "Expires",316 "Content-Location", "Content-MD5", "Last-Modified"]:317 if response.headers.has_key(key):318 del response.headers[key]319 320 if status != 416:321 # A server sending a response with status code 416 (Requested322 # range not satisfiable) SHOULD include a Content-Range field323 # with a byte-range- resp-spec of "*". The instance-length324 # specifies the current length of the selected resource.325 # A response with status code 206 (Partial Content) MUST NOT326 # include a Content-Range field with a byte-range- resp-spec of "*".327 if response.headers.has_key("Content-Range"):328 del response.headers["Content-Range"]329 330 # In all cases, finalize will be called after this method,331 # so don't bother cleaning up response values here.332 response.status = status333 content = getErrorPage(status, traceback=tb, message=message)334 response.body = content335 response.headers['Content-Length'] = len(content)336 response.headers['Content-Type'] = "text/html"337 338 be_ie_unfriendly(status)339 340 341 _ie_friendly_error_sizes = {342 400: 512, 403: 256, 404: 512, 405: 256,343 406: 512, 408: 512, 409: 512, 410: 256,344 500: 512, 501: 512, 505: 512,345 }346 347 348 def be_ie_unfriendly(status):349 350 response = cherrypy.response351 352 # For some statuses, Internet Explorer 5+ shows "friendly error353 # messages" instead of our response.body if the body is smaller354 # than a given size. Fix this by returning a body over that size355 # (by adding whitespace).356 # See http://support.microsoft.com/kb/q218155/357 s = _ie_friendly_error_sizes.get(status, 0)358 if s:359 s += 1360 # Since we are issuing an HTTP error status, we assume that361 # the entity is short, and we should just collapse it.362 content = response.collapse_body()363 l = len(content)364 if l and l < s:365 # IN ADDITION: the response must be written to IE366 # in one chunk or it will still get replaced! Bah.367 content = content + (" " * (s - l))368 response.body = content369 response.headers['Content-Length'] = len(content)370 371 def lower_to_camel(s):372 """Turns lowercase_with_underscore into camelCase."""373 sp = s.split('_')374 new_sp = []375 for i, s in enumerate(sp):376 if i != 0:377 s = s[0].upper() + s[1:]378 new_sp.append(s)379 return ''.join(new_sp)380 381 def formatExc(exc=None):382 """formatExc(exc=None) -> exc (or sys.exc_info if None), formatted."""383 if exc is None:384 exc = sys.exc_info()385 386 if exc == (None, None, None):387 return ""388 389 page_handler_str = ""390 args = list(getattr(exc[1], "args", []))391 if args:392 if len(args) > 1:393 page_handler = args.pop()394 page_handler_str = 'Page handler: %s\n' % repr(page_handler)395 exc[1].args = tuple(args)396 return page_handler_str + "".join(traceback.format_exception(*exc))397 398 def bareError(extrabody=None):399 """Produce status, headers, body for a critical error.400 401 Returns a triple without calling any other questionable functions,402 so it should be as error-free as possible. Call it from an HTTP server403 if you get errors after Request() is done.404 405 If extrabody is None, a friendly but rather unhelpful error message406 is set in the body. If extrabody is a string, it will be appended407 as-is to the body.408 """409 410 # The whole point of this function is to be a last line-of-defense411 # in handling errors. That is, it must not raise any errors itself;412 # it cannot be allowed to fail. Therefore, don't add to it!413 # In particular, don't call any other CP functions.414 415 body = "Unrecoverable error in the server."416 if extrabody is not None:417 body += "\n" + extrabody418 419 return ("500 Internal Server Error",420 [('Content-Type', 'text/plain'),421 ('Content-Length', str(len(body)))],422 [body])423 trunk/cherrypy/_cpwsgi.py
r1013 r1082 4 4 import cherrypy 5 5 from cherrypy import _cputil, _cpwsgiserver 6 from cherrypy._cperror import format_exc, bare_error 6 7 from cherrypy.lib import httptools 7 8 8 9 9 def request Line(environ):10 def request_line(environ): 10 11 """Rebuild first line of the request (e.g. "GET /path HTTP/1.0").""" 11 12 … … 71 72 request.multiprocess = environ['wsgi.multiprocess'] 72 73 request.wsgi_environ = environ 73 response = request.run(request Line(environ),74 response = request.run(request_line(environ), 74 75 translate_headers(environ), 75 76 environ['wsgi.input']) … … 81 82 if cherrypy.config.get("server.throw_errors", False): 82 83 raise 83 tb = _cputil.formatExc()84 tb = format_exc() 84 85 cherrypy.log(tb) 85 86 if not cherrypy.config.get("server.show_tracebacks", False): 86 87 tb = "" 87 s, h, b = _cputil.bareError(tb)88 s, h, b = bare_error(tb) 88 89 exc = sys.exc_info() 89 90 … … 115 116 cherrypy.log(traceback=True) 116 117 request = None 117 s, h, b = _cputil.bareError()118 # CherryPy test suite expects bare Error body to be output,118 s, h, b = bare_error() 119 # CherryPy test suite expects bare_error body to be output, 119 120 # so don't call start_response (which, according to PEP 333, 120 121 # may raise its own error at that point). trunk/cherrypy/config.py
r1069 r1082 21 21 'server.protocol_version': 'HTTP/1.0', 22 22 'server.log_to_screen': True, 23 'server.log_tracebacks': True,24 23 'server.log_file': '', 24 'tools.log_tracebacks.on': True, 25 25 'server.reverse_dns': False, 26 26 'server.thread_pool': 10, … … 230 230 'server.log_to_screen', 231 231 'server.log_file', 232 'server.log_tracebacks',233 'server.log_request_headers',234 232 'server.protocol_version', 235 233 'server.socket_host', trunk/cherrypy/lib/cptools.py
r1070 r1082 7 7 8 8 import cherrypy 9 10 9 11 10 … … 315 314 cherrypy.request.object_path = prefix + "/" + cherrypy.request.object_path 316 315 317 316 def log_traceback(): 317 """Write the last error's traceback to the cherrypy error log.""" 318 from cherrypy import _cperror 319 cherrypy.log(_cperror.format_exc(), "HTTP") 320 321 def log_request_headers(): 322 """Write the last error's traceback to the cherrypy error log.""" 323 h = [" %s: %s" % (k, v) for k, v in cherrypy.request.header_list] 324 cherrypy.log('\nRequest Headers:\n' + '\n'.join(h), "HTTP") 325 326 def redirect(url=''): 327 """Raise cherrypy.HTTPRedirect to the given url.""" 328 raise cherrypy.HTTPRedirect(url) trunk/cherrypy/lib/httptools.py
r1015 r1082 304 304 return code, reason, message 305 305 306 def parse RequestLine(requestLine):307 """Return (method, path, querystring, protocol) from a request Line."""308 method, path, protocol = request Line.split()306 def parse_request_line(request_line): 307 """Return (method, path, querystring, protocol) from a request_line.""" 308 method, path, protocol = request_line.split() 309 309 310 310 # path may be an abs_path (including "http://host.domain.tld"); trunk/cherrypy/lib/sessions.py
r1079 r1082 362 362 363 363 # Users access sessions through cherrypy.session, but we want this 364 # to be thread-specific so we use a special wrapper that forwards365 # callsto cherrypy.session to a thread-specific dictionary called364 # to be thread-specific so we use a wrapper that forwards calls 365 # to cherrypy.session to a thread-specific dictionary called 366 366 # cherrypy.request._session.data 367 367 class SessionWrapper: trunk/cherrypy/lib/wsgiapp.py
r1070 r1082 92 92 """A custom Request object for running a WSGI app within CP.""" 93 93 94 def process Body(self):94 def process_body(self): 95 95 pass 96 96 trunk/cherrypy/lib/xmlrpc.py
r1075 r1082 41 41 allow_none=allow_none)) 42 42 43 def wrap_error():43 def on_error(): 44 44 body = str(sys.exc_info()[1]) 45 45 _set_response(xmlrpclib.dumps(xmlrpclib.Fault(1, body))) trunk/cherrypy/test/benchmark.py
r1070 r1082 87 87 pass 88 88 89 def run(self, request Line, headers, rfile):89 def run(self, request_line, headers, rfile): 90 90 cherrypy.response.status = "204 No Content" 91 91 cherrypy.response.header_list = [("Content-Type", 'text/html'), trunk/cherrypy/test/helper.py
r1035 r1082 55 55 56 56 # This will never contain a traceback: 57 page = cherrypy._cp util.getErrorPage(status, message=message)57 page = cherrypy._cperror.get_error_page(status, message=message) 58 58 59 59 # First, test the response body without checking the traceback. trunk/cherrypy/test/test_config.py
r1069 r1082 95 95 err = ('WrongConfigValue: ("section: ' 96 96 "'global', option: 'server.environment', value: 'production'" 97 '''", 'UnknownType' )''')97 '''", 'UnknownType', ('production',))''') 98 98 self.getPage("/env/wrong") 99 99 self.assertErrorPage(500, pattern=err) trunk/cherrypy/test/test_core.py
r1075 r1082 105 105 106 106 class Error: 107 def _cp_on_error(self): 108 raise cherrypy.HTTPRedirect("/errpage") 107 _cp_tools = [tools.ErrorRedirect("/errpage")] 109 108 110 109 def index(self): … … 207 206 # Since status must start with an int, this should error. 208 207 cherrypy.response.status = "ZOO OK" 209 210 def log_unhandled(self):211 raise ValueError()212 208 213 209 def rethrow(self): … … 356 352 '/error': { 357 353 'server.log_file': log_file, 358 ' server.log_tracebacks': True,354 'tools.log_tracebacks.on': True, 359 355 }, 360 356 '/error/page_streamed': { … … 370 366 'error_page.404': "nonexistent.html", 371 367 }, 372 '/error/log_unhandled': {373 'server.log_tracebacks': False,374 'server.log_unhandled_tracebacks': True,375 },376 368 '/error/rethrow': { 377 369 'server.throw_errors': True, … … 488 480 self.assertEqual(data[0][-41:], ' INFO Traceback (most recent call last):\n') 489 481 self.assertEqual(data[-3], ' raise ValueError()\n') 490 491 # Test that unhandled tracebacks get written
