wsgi: simplified send logic

This commit is contained in:
Mike Barton
2009-06-24 14:25:19 -05:00
parent 552b67f588
commit e8acf88839
2 changed files with 43 additions and 33 deletions

View File

@@ -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()

View File

@@ -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()