From e7cb79779582bc4a27062795ab401adbf1faea57 Mon Sep 17 00:00:00 2001 From: Pierce Lopez Date: Mon, 5 Jun 2017 00:48:45 -0400 Subject: [PATCH 1/2] http1connection: add "Connection: close" header if appropriate When HTTP1Connection acts as the server, it closes the connection after writing the response if the client includes the "Connection: close" header in the request, or if the `no_keep_alive` option is set to True in the constructor. According to https://tools.ietf.org/html/rfc7230#section-6.6 > The server SHOULD send a "close" connection option in its final response on that connection. It was possible for an Application to set the Connection header appropriately. But it is very helpful for tornado to take care of this automatically, particularly if "close" was specified in a request header. --- tornado/http1connection.py | 6 +++++- tornado/test/httpserver_test.py | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tornado/http1connection.py b/tornado/http1connection.py index c6d3e336fb..b7a62b8c0c 100644 --- a/tornado/http1connection.py +++ b/tornado/http1connection.py @@ -357,6 +357,10 @@ def write_headers(self, start_line, headers, chunk=None, callback=None): # Applications are discouraged from touching Transfer-Encoding, # but if they do, leave it alone. 'Transfer-Encoding' not in headers) + # If connection to a 1.1 client will be closed, inform client + if (self._request_start_line.version == 'HTTP/1.1' and + self._disconnect_on_finish): + headers['Connection'] = 'close' # If a 1.0 client asked for keep-alive, add the header. if (self._request_start_line.version == 'HTTP/1.0' and (self._request_headers.get('Connection', '').lower() == @@ -418,7 +422,7 @@ def _format_chunk(self, chunk): def write(self, chunk, callback=None): """Implements `.HTTPConnection.write`. - For backwards compatibility is is allowed but deprecated to + For backwards compatibility it is allowed but deprecated to skip `write_headers` and instead call `write()` with a pre-encoded header block. """ diff --git a/tornado/test/httpserver_test.py b/tornado/test/httpserver_test.py index f5f91a9df2..d8342f748d 100644 --- a/tornado/test/httpserver_test.py +++ b/tornado/test/httpserver_test.py @@ -719,6 +719,7 @@ def test_request_close(self): self.stream.read_until_close(callback=self.stop) data = self.wait() self.assertTrue(not data) + self.assertEqual(self.headers['Connection'], 'close') self.close() # keepalive is supported for http 1.0 too, but it's opt-in From 6d6d44e0fcd2e37299e0ee1f2eec1b6f9be8d7fc Mon Sep 17 00:00:00 2001 From: Pierce Lopez Date: Mon, 5 Jun 2017 13:22:39 -0400 Subject: [PATCH 2/2] httpserver: remove unused no_keep_alive attribute still a parameter passed on to HTTP1Connection --- tornado/httpserver.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tornado/httpserver.py b/tornado/httpserver.py index 7a7d08cd25..95273a3604 100644 --- a/tornado/httpserver.py +++ b/tornado/httpserver.py @@ -154,7 +154,6 @@ def initialize(self, request_callback, no_keep_alive=False, max_body_size=None, max_buffer_size=None, trusted_downstream=None): self.request_callback = request_callback - self.no_keep_alive = no_keep_alive self.xheaders = xheaders self.protocol = protocol self.conn_params = HTTP1ConnectionParameters(