From e8acf888394c1e8db7a1d659eea4cd5e2cadd3b4 Mon Sep 17 00:00:00 2001 From: Mike Barton Date: Wed, 24 Jun 2009 14:25:19 -0500 Subject: [PATCH] wsgi: simplified send logic --- eventlet/wsgi.py | 51 +++++++++++++++--------------------------- greentest/wsgi_test.py | 25 +++++++++++++++++++++ 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py index 85fe4c9..dd9d2a3 100644 --- a/eventlet/wsgi.py +++ b/eventlet/wsgi.py @@ -181,9 +181,8 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): header_dict = {} wfile = self.wfile - num_blocks = None result = None - use_chunked = False + use_chunked = [False] length = [0] status_code = [200] @@ -203,17 +202,15 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): # send Date header? if 'date' not in header_dict: towrite.append('Date: %s\r\n' % (format_date_time(time.time()),)) - if num_blocks is not None: - if 'content-length' not in header_dict: - towrite.append('Content-Length: %s\r\n' % (len(''.join(result)),)) - elif use_chunked: - towrite.append('Transfer-Encoding: chunked\r\n') - else: + if self.request_version == 'HTTP/1.0': towrite.append('Connection: close\r\n') self.close_connection = 1 + elif 'content-length' not in header_dict: + use_chunked[0] = True + towrite.append('Transfer-Encoding: chunked\r\n') towrite.append('\r\n') - if use_chunked: + if use_chunked[0]: ## Write the chunked encoding towrite.append("%x\r\n%s\r\n" % (len(data), data)) else: @@ -258,37 +255,25 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): start_response("500 Internal Server Error", [('Content-type', 'text/plain')]) write(exc) return - try: - num_blocks = len(result) - except (TypeError, AttributeError, NotImplementedError): - if self.request_version == 'HTTP/1.1': - use_chunked = True + if not headers_sent and hasattr(result, '__len__'): + headers_set[1].append(('content-length', str(sum(map(len, result))))) try: try: towrite = [] - try: - for data in result: - if data: - towrite.append(data) - if use_chunked and sum(map(len, towrite)) > self.minimum_chunk_size: - write(''.join(towrite)) - del towrite[:] - except Exception, e: - exc = traceback.format_exc() - print exc - if not headers_set: - start_response("500 Internal Server Error", [('Content-type', 'text/plain')]) - write(exc) - return - - if towrite: - write(''.join(towrite)) + for data in result: + if data: + write(data) if not headers_sent: write('') - if use_chunked: + if use_chunked[0]: wfile.write('0\r\n\r\n') except Exception, e: - traceback.print_exc() + exc = traceback.format_exc() + print exc + if not headers_set: + start_response("500 Internal Server Error", [('Content-type', 'text/plain')]) + write(exc) + return finally: if hasattr(result, 'close'): result.close() diff --git a/greentest/wsgi_test.py b/greentest/wsgi_test.py index 5a3ce78..3fe4646 100644 --- a/greentest/wsgi_test.py +++ b/greentest/wsgi_test.py @@ -57,6 +57,16 @@ def big_chunks(env, start_response): for x in range(10): yield line +def use_write(env, start_response): + if env['PATH_INFO'] == '/a': + write = start_response('200 OK', [('Content-type', 'text/plain'), + ('Content-Length', '5')]) + write('abcde') + if env['PATH_INFO'] == '/b': + write = start_response('200 OK', [('Content-type', 'text/plain')]) + write('abcde') + return [] + def chunked_post(env, start_response): start_response('200 OK', [('Content-type', 'text/plain')]) if env['PATH_INFO'] == '/a': @@ -328,5 +338,20 @@ class TestHttpd(TestCase): response = fd.read(8192) self.assert_(response == 'oh hai', 'invalid response %s' % response) + def test_015_write(self): + self.site.application = use_write + sock = api.connect_tcp(('127.0.0.1', 12346)) + fd = sock.makeGreenFile() + fd.write('GET /a HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n') + response_line, headers, body = read_http(sock) + self.assert_('content-length' in headers) + + sock = api.connect_tcp(('127.0.0.1', 12346)) + fd = sock.makeGreenFile() + fd.write('GET /b HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n') + response_line, headers, body = read_http(sock) + self.assert_('transfer-encoding' in headers) + self.assert_(headers['transfer-encoding'] == 'chunked') + if __name__ == '__main__': main()