]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Move gzip decompression from simple_httpclient to http1connection.
authorBen Darnell <ben@bendarnell.com>
Mon, 3 Mar 2014 02:26:15 +0000 (21:26 -0500)
committerBen Darnell <ben@bendarnell.com>
Mon, 3 Mar 2014 02:26:15 +0000 (21:26 -0500)
tornado/http1connection.py
tornado/simple_httpclient.py

index 8f78e82664007759fa23e8a4ae589547daa97d3b..cc14379fd2f7f2911db64f4ecd1d5636a3e46374 100644 (file)
@@ -23,6 +23,7 @@ from tornado import httputil
 from tornado import iostream
 from tornado.log import gen_log
 from tornado import stack_context
+from tornado.util import GzipDecompressor
 
 
 class HTTP1Connection(object):
@@ -68,7 +69,9 @@ class HTTP1Connection(object):
             if not ret:
                 return
 
-    def read_response(self, delegate, method):
+    def read_response(self, delegate, method, use_gzip=False):
+        if use_gzip:
+            delegate = _GzipMessageDelegate(delegate)
         return self._read_message(delegate, True, method=method)
 
     @gen.coroutine
@@ -247,3 +250,33 @@ class HTTP1Connection(object):
     def _read_body_until_close(self, delegate):
         body = yield self.stream.read_until_close()
         delegate.data_received(body)
+
+
+class _GzipMessageDelegate(httputil.HTTPMessageDelegate):
+    """Wraps an `HTTPMessageDelegate` to decode ``Content-Encoding: gzip``.
+    """
+    def __init__(self, delegate):
+        self._delegate = delegate
+        self._decompressor = None
+
+    def headers_received(self, start_line, headers):
+        if headers.get("Content-Encoding") == "gzip":
+            self._decompressor = GzipDecompressor()
+        return self._delegate.headers_received(start_line, headers)
+
+    def data_received(self, chunk):
+        if self._decompressor:
+            chunk = self._decompressor.decompress(chunk)
+        return self._delegate.data_received(chunk)
+
+    def finish(self):
+        if self._decompressor is not None:
+            tail = self._decompressor.flush()
+            if tail:
+                # I believe the tail will always be empty (i.e.
+                # decompress will return all it can).  The purpose
+                # of the flush call is to detect errors such
+                # as truncated input.  But in case it ever returns
+                # anything, treat it as an extra chunk
+                self._delegate.data_received(tail)
+        return self._delegate.finish()
index 0b837369c33b482fa5afc94cc2151c4555e3a30e..acc8984398235054a307ac49c1a7979fed6d48a8 100644 (file)
@@ -9,7 +9,6 @@ from tornado.iostream import IOStream, SSLIOStream, StreamClosedError
 from tornado.netutil import Resolver, OverrideResolver
 from tornado.log import gen_log
 from tornado import stack_context
-from tornado.util import GzipDecompressor
 
 import base64
 import collections
@@ -341,7 +340,8 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
         # Ensure that any exception raised in read_response ends up in our
         # stack context.
         self.io_loop.add_future(
-            self.connection.read_response(self, method=self.request.method),
+            self.connection.read_response(self, method=self.request.method,
+                                          use_gzip=self.request.use_gzip),
             lambda f: f.result())
 
     def _release(self):
@@ -421,23 +421,7 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
                 raise ValueError("Response with code %d should not have body" %
                                  self.code)
 
-        if (self.request.use_gzip and
-                self.headers.get("Content-Encoding") == "gzip"):
-            self._decompressor = GzipDecompressor()
-
     def finish(self):
-        if self._decompressor is not None:
-            tail = self._decompressor.flush()
-            if tail:
-                # I believe the tail will always be empty (i.e.
-                # decompress will return all it can).  The purpose
-                # of the flush call is to detect errors such
-                # as truncated input.  But in case it ever returns
-                # anything, treat it as an extra chunk
-                if self.request.streaming_callback is not None:
-                    self.request.streaming_callback(tail)
-                else:
-                    self.chunks.append(tail)
         data = b''.join(self.chunks)
         self._remove_timeout()
         original_request = getattr(self.request, "original_request",
@@ -491,8 +475,6 @@ class _HTTPConnection(httputil.HTTPMessageDelegate):
         self.stream.close()
 
     def data_received(self, chunk):
-        if self._decompressor:
-            chunk = self._decompressor.decompress(chunk)
         if self.request.streaming_callback is not None:
             self.request.streaming_callback(chunk)
         else: