diff --git a/src/calibre/srv/http_response.py b/src/calibre/srv/http_response.py index 07e7c35744..04e786a098 100644 --- a/src/calibre/srv/http_response.py +++ b/src/calibre/srv/http_response.py @@ -27,6 +27,7 @@ from calibre.utils.monotonic import monotonic Range = namedtuple('Range', 'start stop size') MULTIPART_SEPARATOR = uuid.uuid4().hex.decode('ascii') +COMPRESSIBLE_TYPES = {'application/json', 'application/javascript', 'application/xml', 'application/oebps-package+xml'} def header_list_to_file(buf): # {{{ buf.append('') @@ -514,10 +515,14 @@ class HTTPConnection(HTTPRequest): if chunk is None: self.set_state(WRITE, self.write_chunk, BytesIO(b'0\r\n\r\n'), output, last=True) else: - if not isinstance(chunk, bytes): - chunk = chunk.encode('utf-8') - chunk = ('%X\r\n' % len(chunk)).encode('ascii') + chunk + b'\r\n' - self.set_state(WRITE, self.write_chunk, BytesIO(chunk), output) + if chunk: + if not isinstance(chunk, bytes): + chunk = chunk.encode('utf-8') + chunk = ('%X\r\n' % len(chunk)).encode('ascii') + chunk + b'\r\n' + self.set_state(WRITE, self.write_chunk, BytesIO(chunk), output) + else: + # Empty chunk, ignore it + self.write_iter(output, event) def write_chunk(self, buf, output, event, last=False): if self.write(buf): @@ -556,7 +561,7 @@ class HTTPConnection(HTTPRequest): output = GeneratedOutput(output) ct = outheaders.get('Content-Type', '').partition(';')[0] compressible = (not ct or ct.startswith('text/') or ct.startswith('image/svg') or - ct in {'application/json', 'application/javascript', 'application/xml'}) + ct.partition(';')[0] in COMPRESSIBLE_TYPES) compressible = (compressible and request.status_code == httplib.OK and (opts.compress_min_size > -1 and output.content_length >= opts.compress_min_size) and acceptable_encoding(request.inheaders.get('Accept-Encoding', '')) and not is_http1) diff --git a/src/calibre/srv/tests/http.py b/src/calibre/srv/tests/http.py index f0dff627a7..379fd76faf 100644 --- a/src/calibre/srv/tests/http.py +++ b/src/calibre/srv/tests/http.py @@ -308,9 +308,12 @@ class TestHTTP(BaseTest): self.ae(r.read(), b'') # Test gzip + raw = b'a'*20000 + server.change_handler(lambda conn: raw) + conn = server.connect() conn.request('GET', '/an_etagged_path', headers={'Accept-Encoding':'gzip'}) r = conn.getresponse() - self.ae(r.status, httplib.OK), self.ae(zlib.decompress(r.read(), 16+zlib.MAX_WBITS), b'an_etagged_path') + self.ae(r.status, httplib.OK), self.ae(zlib.decompress(r.read(), 16+zlib.MAX_WBITS), raw) # Test getting a filesystem file for use_sendfile in (True, False):