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 = {} header_dict = {}
wfile = self.wfile wfile = self.wfile
num_blocks = None
result = None result = None
use_chunked = False use_chunked = [False]
length = [0] length = [0]
status_code = [200] status_code = [200]
@@ -203,17 +202,15 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
# send Date header? # send Date header?
if 'date' not in header_dict: if 'date' not in header_dict:
towrite.append('Date: %s\r\n' % (format_date_time(time.time()),)) towrite.append('Date: %s\r\n' % (format_date_time(time.time()),))
if num_blocks is not None: if self.request_version == 'HTTP/1.0':
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:
towrite.append('Connection: close\r\n') towrite.append('Connection: close\r\n')
self.close_connection = 1 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') towrite.append('\r\n')
if use_chunked: if use_chunked[0]:
## Write the chunked encoding ## Write the chunked encoding
towrite.append("%x\r\n%s\r\n" % (len(data), data)) towrite.append("%x\r\n%s\r\n" % (len(data), data))
else: else:
@@ -258,37 +255,25 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
start_response("500 Internal Server Error", [('Content-type', 'text/plain')]) start_response("500 Internal Server Error", [('Content-type', 'text/plain')])
write(exc) write(exc)
return return
try: if not headers_sent and hasattr(result, '__len__'):
num_blocks = len(result) headers_set[1].append(('content-length', str(sum(map(len, result)))))
except (TypeError, AttributeError, NotImplementedError):
if self.request_version == 'HTTP/1.1':
use_chunked = True
try: try:
try: try:
towrite = [] towrite = []
try: for data in result:
for data in result: if data:
if data: write(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))
if not headers_sent: if not headers_sent:
write('') write('')
if use_chunked: if use_chunked[0]:
wfile.write('0\r\n\r\n') wfile.write('0\r\n\r\n')
except Exception, e: 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: finally:
if hasattr(result, 'close'): if hasattr(result, 'close'):
result.close() result.close()

View File

@@ -57,6 +57,16 @@ def big_chunks(env, start_response):
for x in range(10): for x in range(10):
yield line 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): def chunked_post(env, start_response):
start_response('200 OK', [('Content-type', 'text/plain')]) start_response('200 OK', [('Content-type', 'text/plain')])
if env['PATH_INFO'] == '/a': if env['PATH_INFO'] == '/a':
@@ -328,5 +338,20 @@ class TestHttpd(TestCase):
response = fd.read(8192) response = fd.read(8192)
self.assert_(response == 'oh hai', 'invalid response %s' % response) 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__': if __name__ == '__main__':
main() main()