]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Move HTTP/1.0 Connection: keep-alive behavior to http1connection.
authorBen Darnell <ben@bendarnell.com>
Mon, 21 Apr 2014 03:26:11 +0000 (23:26 -0400)
committerBen Darnell <ben@bendarnell.com>
Mon, 21 Apr 2014 03:26:11 +0000 (23:26 -0400)
Also remove the supports_http_1_1 check from GzipContentEncoding
since versions don't really matter with the accept-encoding check.

tornado/http1connection.py
tornado/test/httpserver_test.py
tornado/web.py

index b06680031084613c46490513ebea3f630f718ac9..342d9efc859fbc2f0c2f8d317118c56f37f00d9d 100644 (file)
@@ -77,6 +77,7 @@ class HTTP1Connection(object):
         # have content-length but no bodies)
         self._request_start_line = None
         self._response_start_line = None
+        self._request_headers = None
         # True if we are writing output with chunked encoding.
         self._chunking_output = None
         # While reading a body with a content-length, this is the
@@ -112,6 +113,7 @@ class HTTP1Connection(object):
             else:
                 start_line = httputil.parse_request_start_line(start_line)
                 self._request_start_line = start_line
+                self._request_headers = headers
 
             self._disconnect_on_finish = not self._can_keep_alive(
                 start_line, headers)
@@ -238,6 +240,11 @@ class HTTP1Connection(object):
                 # Applications are discouraged from touching Transfer-Encoding,
                 # but if they do, leave it alone.
                 'Transfer-Encoding' not in headers)
+            # 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()
+                 == 'keep-alive')):
+                headers['Connection'] = 'Keep-Alive'
         if self._chunking_output:
             headers['Transfer-Encoding'] = 'chunked'
         if (not self.is_client and
index 22ef7eccc06f41a3a0c646477d8385bc2ad18759..dc31dc54c96f0ea2c9853353f1dd70873e122b75 100644 (file)
@@ -33,14 +33,18 @@ except ImportError:
 
 
 def read_stream_body(stream, callback):
-    """Reads an HTTP response from `stream` and runs callback with its body."""
+    """Reads an HTTP response from `stream` and runs callback with its
+    headers and body."""
     chunks = []
     class Delegate(HTTPMessageDelegate):
+        def headers_received(self, start_line, headers):
+            self.headers = headers
+
         def data_received(self, chunk):
             chunks.append(chunk)
 
         def finish(self):
-            callback(b''.join(chunks))
+            callback((self.headers, b''.join(chunks)))
     conn = HTTP1Connection(stream, True)
     conn.read_response(Delegate())
 
@@ -202,7 +206,8 @@ class HTTPConnectionTest(AsyncHTTPTestCase):
                              [utf8("Content-Length: %d\r\n" % len(body))]) +
                 b"\r\n" + body)
             read_stream_body(stream, self.stop)
-            return self.wait()
+            headers, body = self.wait()
+            return body
 
     def test_multipart_form(self):
         # Encodings here are tricky:  Headers are latin1, bodies can be
@@ -415,7 +420,7 @@ bar
 
 """.replace(b"\n", b"\r\n"))
         read_stream_body(self.stream, self.stop)
-        response = self.wait()
+        headers, response = self.wait()
         self.assertEqual(json_decode(response), {u('foo'): [u('bar')]})
 
 
@@ -631,8 +636,8 @@ class KeepAliveTest(AsyncHTTPTestCase):
         return headers
 
     def read_response(self):
-        headers = self.read_headers()
-        self.stream.read_bytes(int(headers['Content-Length']), self.stop)
+        self.headers = self.read_headers()
+        self.stream.read_bytes(int(self.headers['Content-Length']), self.stop)
         body = self.wait()
         self.assertEqual(b'Hello world', body)
 
@@ -666,6 +671,7 @@ class KeepAliveTest(AsyncHTTPTestCase):
         self.stream.read_until_close(callback=self.stop)
         data = self.wait()
         self.assertTrue(not data)
+        self.assertTrue('Connection' not in self.headers)
         self.close()
 
     def test_http10_keepalive(self):
@@ -673,8 +679,10 @@ class KeepAliveTest(AsyncHTTPTestCase):
         self.connect()
         self.stream.write(b'GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n')
         self.read_response()
+        self.assertEqual(self.headers['Connection'], 'Keep-Alive')
         self.stream.write(b'GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n')
         self.read_response()
+        self.assertEqual(self.headers['Connection'], 'Keep-Alive')
         self.close()
 
     def test_pipelined_requests(self):
@@ -993,7 +1001,7 @@ class BodyLimitsTest(AsyncHTTPTestCase):
             stream.write(b'PUT /streaming?expected_size=10240 HTTP/1.1\r\n'
                          b'Content-Length: 10240\r\n\r\n')
             stream.write(b'a'*10240)
-            response = yield gen.Task(read_stream_body, stream)
+            headers, response = yield gen.Task(read_stream_body, stream)
             self.assertEqual(response, b'10240')
             # Without the ?expected_size parameter, we get the old default value
             stream.write(b'PUT /streaming HTTP/1.1\r\n'
index c318f33c0c70cfede40f05778fa43eb5ddc9e73b..37c5f715bcb586f3600ea26770700979fbe268be 100644 (file)
@@ -244,12 +244,6 @@ class RequestHandler(object):
             "Date": httputil.format_timestamp(time.time()),
         })
         self.set_default_headers()
-        if (not self.request.supports_http_1_1() and
-            getattr(self.request, 'connection', None) and
-                not self.request.connection.no_keep_alive):
-            conn_header = self.request.headers.get("Connection")
-            if conn_header and (conn_header.lower() == "keep-alive"):
-                self._headers["Connection"] = "Keep-Alive"
         self._write_buffer = []
         self._status_code = 200
         self._reason = httputil.responses[200]
@@ -2380,8 +2374,7 @@ class GZipContentEncoding(OutputTransform):
     MIN_LENGTH = 5
 
     def __init__(self, request):
-        self._gzipping = request.supports_http_1_1() and \
-            "gzip" in request.headers.get("Accept-Encoding", "")
+        self._gzipping = "gzip" in request.headers.get("Accept-Encoding", "")
 
     def _compressible_type(self, ctype):
         return ctype.startswith('text/') or ctype in self.CONTENT_TYPES