Index: http/response.py =================================================================== --- http/response.py (revision 57) +++ http/response.py (working copy) @@ -111,6 +111,8 @@ added. compress : bool should the body of the response be compressed? + chunked : bool + should the response be Transfer-Encoding chunked """ def __init__(self): @@ -119,6 +121,7 @@ self.set_compress(False) self.set_expires(0) self.set_buffered(True) + self.set_chunked(False) self.headers = {} self.cookies = {} self.body = None @@ -140,6 +143,12 @@ def get_compress(self): return self.compress + def set_chunked(self, value): + self.chunked = value + + def get_chunked(self): + return self.chunked + def set_buffered(self, value): self.buffered = value @@ -349,8 +358,13 @@ length = self.get_content_length() if length is not None: yield ('Content-Length', str(length)) - - + else: + # Transfer-Encoding + self.set_chunked(True) + yield ('Transfer-Encoding', 'chunked') + if self.get_compress() and self.get_mime_type() not in _GZIP_EXCLUDE: + yield ("Content-Encoding", "gzip") + def generate_body_chunks(self): """ Return a sequence of body chunks, encoded using 'charset'. @@ -360,8 +374,31 @@ if self.body is None: pass elif isinstance(self.body, Stream): - for chunk in self.body: - yield self._encode_chunk(chunk) + if self.get_chunked() and self.get_compress() and self.get_mime_type() not in _GZIP_EXCLUDE: + co = crc = clen = gz_chunk = None + crc = zlib.crc32("") + clen = 0 + co = zlib.compressobj(6, zlib.DEFLATED, -zlib.MAX_WBITS, + zlib.DEF_MEM_LEVEL, 0) + yield _GZIP_HEADER + for chunk in self.body: + clen += len(chunk) + crc = zlib.crc32(chunk, crc) + + gz_chunk = co.compress(self._encode_chunk(chunk)) + if not gz_chunk: + continue + + yield gz_chunk + + gz_chunk = co.flush() + yield gz_chunk + end = struct.pack("