tests: wsgi: close socket on error in the middle of chunked response

http://rhodesmill.org/brandon/2013/chunked-wsgi/
This commit is contained in:
Sergey Shepelev
2013-02-22 14:19:48 +04:00
parent e0b30d4f77
commit e06b8698e7

View File

@@ -43,12 +43,35 @@ def chunked_app(env, start_response):
yield "chunked"
def chunked_fail_app(environ, start_response):
"""http://rhodesmill.org/brandon/2013/chunked-wsgi/
"""
headers = [('Content-Type', 'text/plain')]
start_response('200 OK', headers)
# We start streaming data just fine.
yield "The dwarves of yore made mighty spells,"
yield "While hammers fell like ringing bells"
# Then the back-end fails!
try:
1 / 0
except Exception:
start_response('500 Error', headers, sys.exc_info())
return
# So rest of the response data is not available.
yield "In places deep, where dark things sleep,"
yield "In hollow halls beneath the fells."
def big_chunks(env, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
line = 'a' * 8192
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'),
@@ -59,6 +82,7 @@ def use_write(env, start_response):
write('abcde')
return []
def chunked_post(env, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
if env['PATH_INFO'] == '/a':
@@ -68,10 +92,12 @@ def chunked_post(env, start_response):
elif env['PATH_INFO'] == '/c':
return [x for x in iter(lambda: env['wsgi.input'].read(1), '')]
def already_handled(env, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
return wsgi.ALREADY_HANDLED
class Site(object):
def __init__(self):
self.application = hello_world
@@ -79,6 +105,7 @@ class Site(object):
def __call__(self, env, start_response):
return self.application(env, start_response)
class IterableApp(object):
def __init__(self, send_start_response=False, return_val=wsgi.ALREADY_HANDLED):
@@ -92,6 +119,7 @@ class IterableApp(object):
start_response('200 OK', [('Content-type', 'text/plain')])
return self.return_val
class IterableSite(Site):
def __call__(self, env, start_response):
it = self.application(env, start_response)
@@ -99,7 +127,6 @@ class IterableSite(Site):
yield i
CONTENT_LENGTH = 'content-length'
@@ -111,6 +138,7 @@ Content-length: 11
hello world
"""
class ConnectionClosed(Exception):
pass
@@ -758,6 +786,25 @@ class TestHttpd(_TestBase):
self.assertNotEqual(headers.get('transfer-encoding'), 'chunked')
self.assertEquals(body, "thisischunked")
def test_error_in_chunked_closes_connection(self):
# From http://rhodesmill.org/brandon/2013/chunked-wsgi/
greenthread.kill(self.killer)
eventlet.sleep(0)
self.spawn_server(minimum_chunk_size=1)
self.site.application = chunked_fail_app
sock = eventlet.connect(('localhost', self.port))
sock.sendall('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
response_line, headers, body = read_http(sock)
self.assertEqual(response_line, 'HTTP/1.1 200 OK\r\n')
self.assertEqual(headers.get('transfer-encoding'), 'chunked')
self.assertEqual(body, '27\r\nThe dwarves of yore made mighty spells,\r\n25\r\nWhile hammers fell like ringing bells\r\n')
# verify that socket is closed by server
self.assertEqual(sock.recv(1), '')
def test_026_http_10_nokeepalive(self):
# verify that if an http/1.0 client sends connection: keep-alive
# and the server doesn't accept keep-alives, we close the connection