diff options
| author | Jakub Stasiak <jakub@stasiak.at> | 2016-02-09 02:24:47 +0100 |
|---|---|---|
| committer | Jakub Stasiak <jakub@stasiak.at> | 2016-02-09 03:17:18 +0100 |
| commit | f011f783db1d9d58ee198dbef35fef9f9d4a6248 (patch) | |
| tree | ccf61f625ed2900f8071a6abad397db057b6c7ca /tests/wsgi_test.py | |
| parent | 8a4a1212b2097c6ecca96c81dc355388583ac45d (diff) | |
| download | eventlet-writelines-fix.tar.gz | |
wsgi: Fix handling partial writeswritelines-fix
Closes https://github.com/eventlet/eventlet/issues/295
Diffstat (limited to 'tests/wsgi_test.py')
| -rw-r--r-- | tests/wsgi_test.py | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py index 50091eb..2c25553 100644 --- a/tests/wsgi_test.py +++ b/tests/wsgi_test.py @@ -10,6 +10,8 @@ import tempfile import traceback import unittest +from nose.tools import eq_ + import eventlet from eventlet import debug from eventlet import event @@ -444,6 +446,43 @@ class TestHttpd(_TestBase): # Require a CRLF to close the message body self.assertEqual(response, b'\r\n') + def test_partial_writes_are_handled(self): + # The bug was caused by the default writelines() implementaiton + # (used by the wsgi module) which doesn't check if write() + # successfully completed sending *all* data therefore data could be + # lost and the client could be left hanging forever. + # + # Eventlet issue: "Python 3: wsgi doesn't handle correctly partial + # write of socket send() when using writelines()", + # https://github.com/eventlet/eventlet/issues/295 + # + # Related CPython issue: "Raw I/O writelines() broken", + # http://bugs.python.org/issue26292 + + # Piece of data large enough that we can reasonably expect it to not + # be sent in one piece. Is there a reliable way to determine this + # number without testing various sizes empirically? + data = b'a' * 10 ** 7 + + def application(env, start_response): + # Sending content-length is important here, otherwise chunked encoding + # is chosen + start_response('200 OK', []) + yield data + + self.site.application = application + + sock = eventlet.connect(('localhost', self.port)) + + # HTTP 1.0 is important here, this tells the server to close the socket + # after sending the data so that read_http() can safely read until EOF + # without hanging forever. + sock.sendall(b'GET / HTTP/1.0\r\nHost: localhost\r\n\r\n') + result = read_http(sock) + + # This would previously fail because part of the data would be lost + eq_(len(result.body), len(data)) + @tests.skip_if_no_ssl def test_012_ssl_server(self): def wsgi_app(environ, start_response): |
