Changeset 1978
- Timestamp:
- 06/07/08 16:10:53
- Files:
-
- trunk/cherrypy/_cpwsgi.py (modified) (3 diffs)
- trunk/cherrypy/test/test_core.py (modified) (1 diff)
- trunk/cherrypy/test/test_encoding.py (modified) (1 diff)
- trunk/cherrypy/test/test_tools.py (modified) (2 diffs)
- trunk/cherrypy/wsgiserver/__init__.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cpwsgi.py
r1969 r1978 75 75 76 76 def setapp(self): 77 # Stage 1: by whatever means necessary, obtain a status, header78 # set and body, with an optional exception object.79 77 try: 80 78 self.request = self.get_request() 81 79 s, h, b = self.get_response() 82 exc = None 80 self.iter_response = iter(b) 81 self.start_response(s, h) 83 82 except self.throws: 84 83 self.close() … … 99 98 tb = "" 100 99 s, h, b = _cperror.bare_error(tb) 101 exc = _sys.exc_info() 102 103 self.iter_response = iter(b) 104 105 # Stage 2: now that we have a status, header set, and body, 106 # finish the WSGI conversation by calling start_response. 107 try: 108 self.start_response(s, h, exc) 109 except self.throws: 110 self.close() 111 raise 112 except: 113 if getattr(self.request, "throw_errors", False): 100 self.iter_response = iter(b) 101 102 try: 103 self.start_response(s, h, _sys.exc_info()) 104 except: 105 # "The application must not trap any exceptions raised by 106 # start_response, if it called start_response with exc_info. 107 # Instead, it should allow such exceptions to propagate 108 # back to the server or gateway." 109 # But we still log and call close() to clean up ourselves. 110 _cherrypy.log(traceback=True, severity=40) 114 111 self.close() 115 112 raise 116 117 _cherrypy.log(traceback=True, severity=40)118 self.close()119 120 # CherryPy test suite expects bare_error body to be output,121 # so don't call start_response (which, according to PEP 333,122 # may raise its own error at that point).123 s, h, b = _cperror.bare_error()124 self.iter_response = iter(b)125 113 126 114 def iredirect(self, path, query_string): … … 194 182 raise 195 183 196 _cherrypy.log(traceback=True, severity=40)197 198 # CherryPy test suite expects bare_error body to be output,199 # so don't call start_response (which, according to PEP 333,200 # may raise its own error at that point).201 s, h, b = _cperror.bare_error()184 tb = _cperror.format_exc() 185 _cherrypy.log(tb, severity=40) 186 if not getattr(self.request, "show_tracebacks", True): 187 tb = "" 188 s, h, b = _cperror.bare_error(tb) 189 # Empty our iterable (so future calls raise StopIteration) 202 190 self.iter_response = iter([]) 191 192 try: 193 self.start_response(s, h, _sys.exc_info()) 194 except: 195 # "The application must not trap any exceptions raised by 196 # start_response, if it called start_response with exc_info. 197 # Instead, it should allow such exceptions to propagate 198 # back to the server or gateway." 199 # But we still log and call close() to clean up ourselves. 200 _cherrypy.log(traceback=True, severity=40) 201 self.close() 202 raise 203 203 204 return "".join(b) 204 205 trunk/cherrypy/test/test_core.py
r1949 r1978 718 718 self.assertErrorPage(500, pattern=valerr) 719 719 720 self.getPage("/error/page_streamed") 721 # Because this error is raised after the response body has 722 # started, the status should not change to an error status. 723 self.assertStatus(200) 724 self.assertBody("word upUnrecoverable error in the server.") 720 if cherrypy.server.protocol_version == "HTTP/1.0": 721 self.getPage("/error/page_streamed") 722 # Because this error is raised after the response body has 723 # started, the status should not change to an error status. 724 self.assertStatus(200) 725 self.assertBody("word up") 726 else: 727 # Under HTTP/1.1, the chunked transfer-coding is used. 728 # The HTTP client will choke when the output is incomplete. 729 self.assertRaises(ValueError, self.getPage, 730 "/error/page_streamed") 725 731 726 732 # No traceback should be present trunk/cherrypy/test/test_encoding.py
r1832 r1978 145 145 # and 2) we may have already written some of the body. 146 146 # The fix is to never stream yields when using gzip. 147 self.getPage('/gzip/noshow_stream', 148 headers=[("Accept-Encoding", "gzip")]) 149 self.assertHeader('Content-Encoding', 'gzip') 150 self.assertMatchesBody(r"Unrecoverable error in the server.$") 147 if cherrypy.server.protocol_version == "HTTP/1.0": 148 self.getPage('/gzip/noshow_stream', 149 headers=[("Accept-Encoding", "gzip")]) 150 self.assertHeader('Content-Encoding', 'gzip') 151 self.assertInBody('\x1f\x8b\x08\x00') 152 else: 153 # The wsgiserver will simply stop sending data, and the HTTP client 154 # will error due to an incomplete chunk-encoded stream. 155 self.assertRaises(ValueError, self.getPage, '/gzip/noshow_stream', 156 headers=[("Accept-Encoding", "gzip")]) 151 157 152 158 trunk/cherrypy/test/test_tools.py
r1960 r1978 171 171 172 172 def errinstream(self, id=None): 173 yield "nonconfidential" 173 174 raise ValueError() 174 175 yield "confidential" … … 256 257 257 258 # If body is "razdrez", then on_end_request is being called too early. 258 self.getPage("/demo/errinstream?id=5") 259 # Because this error is raised after the response body has 260 # started, the status should not change to an error status. 261 self.assertStatus("200 OK") 262 self.assertBody("Unrecoverable error in the server.") 259 if cherrypy.server.protocol_version == "HTTP/1.0": 260 self.getPage("/demo/errinstream?id=5") 261 # Because this error is raised after the response body has 262 # started, the status should not change to an error status. 263 self.assertStatus("200 OK") 264 self.assertBody("nonconfidential") 265 else: 266 # Because this error is raised after the response body has 267 # started, and because it's chunked output, an error is raised by 268 # the HTTP client when it encounters incomplete output. 269 self.assertRaises(ValueError, self.getPage, 270 "/demo/errinstream?id=5") 263 271 # If this fails, then on_end_request isn't being called at all. 264 272 time.sleep(0.1) trunk/cherrypy/wsgiserver/__init__.py
r1971 r1978 538 538 self._respond() 539 539 except MaxSizeExceeded: 540 self.simple_response("413 Request Entity Too Large") 540 if not self.sent_headers: 541 self.simple_response("413 Request Entity Too Large") 541 542 return 542 543 … … 587 588 def start_response(self, status, headers, exc_info = None): 588 589 """WSGI callable to begin the HTTP response.""" 589 if self.started_response: 590 if not exc_info: 591 raise AssertionError("WSGI start_response called a second " 592 "time with no exc_info.") 593 else: 594 try: 595 raise exc_info[0], exc_info[1], exc_info[2] 596 finally: 597 exc_info = None 590 # "The application may call start_response more than once, 591 # if and only if the exc_info argument is provided." 592 if self.started_response and not exc_info: 593 raise AssertionError("WSGI start_response called a second " 594 "time with no exc_info.") 595 596 # "if exc_info is provided, and the HTTP headers have already been 597 # sent, start_response must raise an error, and should raise the 598 # exc_info tuple." 599 if self.sent_headers: 600 try: 601 raise exc_info[0], exc_info[1], exc_info[2] 602 finally: 603 exc_info = None 604 598 605 self.started_response = True 599 606 self.status = status … … 980 987 errnum = e.args[0] 981 988 if errnum == 'timed out': 982 if req :989 if req and not req.sent_headers: 983 990 req.simple_response("408 Request Timeout") 984 991 elif errnum not in socket_errors_to_ignore: 985 if req :992 if req and not req.sent_headers: 986 993 req.simple_response("500 Internal Server Error", 987 994 format_exc()) … … 995 1002 # Unwrap our wfile 996 1003 req.wfile = CP_fileobject(self.socket, "wb", -1) 997 req.simple_response("400 Bad Request", 998 "The client sent a plain HTTP request, but " 999 "this server only speaks HTTPS on this port.") 1004 if req and not req.sent_headers: 1005 req.simple_response("400 Bad Request", 1006 "The client sent a plain HTTP request, but " 1007 "this server only speaks HTTPS on this port.") 1000 1008 except Exception, e: 1001 if req :1009 if req and not req.sent_headers: 1002 1010 req.simple_response("500 Internal Server Error", format_exc()) 1003 1011

