Changeset 851
- Timestamp:
- 11/28/05 16:36:07
- Files:
-
- trunk/cherrypy/_cphttpserver.py (modified) (1 diff)
- trunk/cherrypy/_cphttptools.py (modified) (1 diff)
- trunk/cherrypy/_cpwsgi.py (modified) (1 diff)
- trunk/cherrypy/test/helper.py (modified) (2 diffs)
- trunk/cherrypy/test/test_core.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cphttpserver.py
r849 r851 75 75 return 76 76 77 request = cherrypy.server.request(self.client_address, 78 self.address_string(), "http") 79 request.multithread = cherrypy.config.get("server.threadPool") > 1 80 request.multiprocess = False 81 response = request.run(self.raw_requestline, self._headerlist(), 82 self.rfile) 83 84 wfile = self.wfile 85 wfile.write("%s %s\r\n" % (self.protocol_version, response.status)) 86 87 has_close_conn = False 88 for name, value in response.headers: 89 wfile.write("%s: %s\r\n" % (name, value)) 90 if name.lower == 'connection' and value.lower == 'close': 91 has_close_conn = True 92 if not has_close_conn: 93 # This server doesn't support persistent connections yet, so we 94 # must add a "Connection: close" header to tell the client that 95 # we will close the connection when we're done sending output. 96 # 97 # From RFC 2616 sec 14.10: 98 # HTTP/1.1 defines the "close" connection option for the sender 99 # to signal that the connection will be closed after completion 100 # of the response. For example, 101 # 102 # Connection: close 103 # 104 # in either the request or the response header fields indicates 105 # that the connection SHOULD NOT be considered `persistent' 106 # (section 8.1) after the current request/response is complete. 107 # 108 # HTTP/1.1 applications that do not support persistent connections 109 # MUST include the "close" connection option in every message. 110 wfile.write("Connection: close\r\n") 111 112 wfile.write("\r\n") 113 try: 114 for chunk in response.body: 77 request = None 78 try: 79 request = cherrypy.server.request(self.client_address, 80 self.address_string(), "http") 81 request.multithread = cherrypy.config.get("server.threadPool") > 1 82 request.multiprocess = False 83 response = request.run(self.raw_requestline, self._headerlist(), 84 self.rfile) 85 s, h, b = response.status, response.headers, response.body 86 exc = None 87 except (KeyboardInterrupt, SystemExit): 88 raise 89 except: 90 tb = _cputil.formatExc() 91 cherrypy.log(tb) 92 if not cherrypy.config.get("server.showTracebacks", False): 93 tb = "" 94 s, h, b = _cputil.bareError(tb) 95 96 try: 97 wfile = self.wfile 98 wfile.write("%s %s\r\n" % (self.protocol_version, s)) 99 100 has_close_conn = False 101 for name, value in h: 102 wfile.write("%s: %s\r\n" % (name, value)) 103 if name.lower == 'connection' and value.lower == 'close': 104 has_close_conn = True 105 if not has_close_conn: 106 # This server doesn't support persistent connections yet, so we 107 # must add a "Connection: close" header to tell the client that 108 # we will close the connection when we're done sending output. 109 # 110 # From RFC 2616 sec 14.10: 111 # HTTP/1.1 defines the "close" connection option for the sender 112 # to signal that the connection will be closed after completion 113 # of the response. For example, 114 # 115 # Connection: close 116 # 117 # in either the request or the response header fields indicates 118 # that the connection SHOULD NOT be considered `persistent' 119 # (section 8.1) after the current request/response is complete. 120 # 121 # HTTP/1.1 applications that do not support persistent connections 122 # MUST include the "close" connection option in every message. 123 wfile.write("Connection: close\r\n") 124 125 wfile.write("\r\n") 126 for chunk in b: 115 127 wfile.write(chunk) 116 request.close() 128 if request: 129 request.close() 130 except (KeyboardInterrupt, SystemExit), ex: 131 try: 132 if request: 133 request.close() 134 except: 135 cherrypy.log(_cputil.formatExc()) 136 raise ex 117 137 except: 138 tb = _cputil.formatExc() 139 try: 140 if request: 141 request.close() 142 except: 143 cherrypy.log(_cputil.formatExc()) 144 cherrypy.log(tb) 118 145 s, h, b = _cputil.bareError() 146 # CherryPy test suite expects bareError body to be output, 147 # so don't call start_response (which, according to PEP 333, 148 # may raise its own error at that point). 119 149 for chunk in b: 120 150 wfile.write(chunk) trunk/cherrypy/_cphttptools.py
r843 r851 31 31 32 32 def close(self): 33 self.closed = True34 try:35 applyFilters('onEndRequest')36 cherrypy.serving.request = None37 cherrypy.serving.response = None38 except (KeyboardInterrupt, SystemExit):39 raise40 except:41 cherrypy.log(_cputil.formatExc())42 43 def __del__(self):44 33 if not self.closed: 45 self.close() 34 self.closed = True 35 try: 36 applyFilters('onEndRequest') 37 except (KeyboardInterrupt, SystemExit): 38 raise 39 except: 40 cherrypy.log(_cputil.formatExc()) 46 41 47 42 def run(self, requestLine, headers, rfile): trunk/cherrypy/_cpwsgi.py
r843 r851 95 95 if request: 96 96 request.close() 97 except (KeyboardInterrupt, SystemExit): 98 raise 97 except (KeyboardInterrupt, SystemExit), ex: 98 try: 99 if request: 100 request.close() 101 except: 102 cherrypy.log(_cputil.formatExc()) 103 raise ex 99 104 except: 100 105 tb = _cputil.formatExc() 106 try: 107 if request: 108 request.close() 109 except: 110 cherrypy.log(_cputil.formatExc()) 101 111 cherrypy.log(tb) 102 112 s, h, b = _cputil.bareError() trunk/cherrypy/test/helper.py
r838 r851 89 89 self.body.append(chunk) 90 90 request.close() 91 except :91 except Exception, ex: 92 92 if cherrypy.config.get("streamResponse", False): 93 try: 94 request.close() 95 except: 96 cherrypy.log(cherrypy._cputil.formatExc()) 93 97 # Pass the error through 94 raise 98 raise ex 95 99 96 from cherrypy import _cputil 97 s, h, b = _cputil.bareError() 100 s, h, b = cherrypy._cputil.bareError() 98 101 # Don't reset status or headers; we're emulating an error which 99 102 # occurs after status and headers have been written to the client. … … 136 139 """ 137 140 138 from cherrypy._cputil import getErrorPage139 140 141 # This will never contain a traceback: 141 page = getErrorPage(status, message=message)142 page = cherrypy._cputil.getErrorPage(status, message=message) 142 143 143 144 # First, test the response body without checking the traceback. trunk/cherrypy/test/test_core.py
r843 r851 328 328 def index(self): 329 329 return "A good piece of cherry pie" 330 331 def err(self): 332 raise ValueError() 333 334 def errinstream(self): 335 raise ValueError() 336 yield "confidential" 330 337 331 338 … … 365 372 'server.logUnhandledTracebacks': True, 366 373 }, 374 '/cpfilterlist/errinstream': { 375 'streamResponse': True, 376 }, 367 377 }) 368 378 … … 575 585 # If this fails, then onEndRequest isn't being called at all. 576 586 self.assertEqual(_nf.ended, True) 587 588 ignore = helper.webtest.ignored_exceptions 589 ignore.append(ValueError) 590 try: 591 valerr = '\n raise ValueError()\nValueError' 592 self.getPage("/cpfilterlist/err") 593 # If body is "razdrez", then onEndRequest is being called too early. 594 self.assertErrorPage(500, pattern=valerr) 595 # If this fails, then onEndRequest isn't being called at all. 596 self.assertEqual(_nf.ended, True) 597 598 # If body is "razdrez", then onEndRequest is being called too early. 599 if cherrypy.server.httpserver is None: 600 self.assertRaises(ValueError, self.getPage, 601 "/cpfilterlist/errinstream") 602 else: 603 self.getPage("/cpfilterlist/errinstream") 604 # Because this error is raised after the response body has 605 # started, the status should not change to an error status. 606 self.assertStatus("200 OK") 607 self.assertBody("Unrecoverable error in the server.") 608 # If this fails, then onEndRequest isn't being called at all. 609 self.assertEqual(_nf.ended, True) 610 finally: 611 ignore.pop() 577 612 578 613 def testFlatten(self):

