diff --git a/tornado/simple_httpclient.py b/tornado/simple_httpclient.py index 376d410c..c301295a 100644 --- a/tornado/simple_httpclient.py +++ b/tornado/simple_httpclient.py @@ -250,6 +250,8 @@ class _HTTPConnection(object): 'proxy_username', 'proxy_password'): if getattr(self.request, key, None): raise NotImplementedError('%s not supported' % key) + if "Connection" not in self.request.headers: + self.request.headers["Connection"] = "close" if "Host" not in self.request.headers: self.request.headers["Host"] = parsed.netloc username, password = None, None @@ -313,6 +315,8 @@ class _HTTPConnection(object): self._run_callback(HTTPResponse(self.request, 599, error=e, request_time=time.time() - self.start_time, )) + if hasattr(self, "stream"): + self.stream.close() def _on_close(self): self._run_callback(HTTPResponse( diff --git a/tornado/test/httpserver_test.py b/tornado/test/httpserver_test.py index 1a53a34f..132af561 100644 --- a/tornado/test/httpserver_test.py +++ b/tornado/test/httpserver_test.py @@ -217,9 +217,10 @@ class HTTPConnectionTest(AsyncHTTPTestCase, LogTrapTestCase): stream.connect(("localhost", self.get_http_port()), callback=self.stop) self.wait() stream.write(b("\r\n").join([b("POST /hello HTTP/1.1"), - b("Content-Length: 1024"), - b("Expect: 100-continue"), - b("\r\n")]), callback=self.stop) + b("Content-Length: 1024"), + b("Expect: 100-continue"), + b("Connection: close"), + b("\r\n")]), callback=self.stop) self.wait() stream.read_until(b("\r\n\r\n"), self.stop) data = self.wait() @@ -234,6 +235,7 @@ class HTTPConnectionTest(AsyncHTTPTestCase, LogTrapTestCase): stream.read_bytes(int(headers["Content-Length"]), self.stop) body = self.wait() self.assertEqual(body, b("Got 1024 bytes in POST")) + stream.close() class EchoHandler(RequestHandler): def get(self): @@ -368,6 +370,8 @@ class UnixSocketTest(AsyncTestCase, LogTrapTestCase): stream.read_bytes(int(headers["Content-Length"]), self.stop) body = self.wait() self.assertEqual(body, b("Hello world")) + stream.close() + server.stop() if not hasattr(socket, 'AF_UNIX') or sys.platform == 'cygwin': del UnixSocketTest diff --git a/tornado/test/iostream_test.py b/tornado/test/iostream_test.py index 43b2e17b..895a3de9 100644 --- a/tornado/test/iostream_test.py +++ b/tornado/test/iostream_test.py @@ -58,6 +58,8 @@ class TestIOStream(AsyncHTTPTestCase, LogTrapTestCase): data = self.wait() self.assertEqual(data, b("200")) + s.close() + def test_write_zero_bytes(self): # Attempting to write zero bytes should run the callback without # going into an infinite loop. @@ -67,6 +69,8 @@ class TestIOStream(AsyncHTTPTestCase, LogTrapTestCase): # As a side effect, the stream is now listening for connection # close (if it wasn't already), but is not listening for writes self.assertEqual(server._state, IOLoop.READ|IOLoop.ERROR) + server.close() + client.close() def test_connection_refused(self): # When a connection is refused, the connect callback should not diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index ebb265b9..030876be 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -32,7 +32,8 @@ class TriggerHandler(RequestHandler): def get(self): logging.info("queuing trigger") self.queue.append(self.finish) - self.wake_callback() + if self.get_argument("wake", "true") == "true": + self.wake_callback() class HangHandler(RequestHandler): @asynchronous @@ -173,10 +174,12 @@ class SimpleHTTPClientTestCase(AsyncHTTPTestCase, LogTrapTestCase): self.assertEqual("POST", response.request.method) def test_request_timeout(self): - response = self.fetch('/hang', request_timeout=0.1) + response = self.fetch('/trigger?wake=false', request_timeout=0.1) self.assertEqual(response.code, 599) self.assertTrue(0.099 < response.request_time < 0.11, response.request_time) self.assertEqual(str(response.error), "HTTP 599: Timeout") + # trigger the hanging request to let it clean up after itself + self.triggers.popleft()() def test_ipv6(self): if not socket.has_ipv6: