/usr/lib/python2.7/dist-packages/cherrypy/filters/gzipfilter.py is in python-cherrypy 2.3.0-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | import struct
import time
import zlib
import cherrypy
from basefilter import BaseFilter
class GzipFilter(BaseFilter):
"""Filter that gzips the response."""
def before_finalize(self):
if not cherrypy.config.get('gzip_filter.on', False):
return
response = cherrypy.response
if not response.body:
# Response body is empty (might be a 304 for instance)
return
def zipit():
# Return a generator that compresses the page
varies = response.headers.get("Vary", "")
varies = [x.strip() for x in varies.split(",") if x.strip()]
if "Accept-Encoding" not in varies:
varies.append("Accept-Encoding")
response.headers['Vary'] = ", ".join(varies)
response.headers['Content-Encoding'] = 'gzip'
level = cherrypy.config.get('gzip_filter.compresslevel', 9)
response.body = self.zip_body(response.body, level)
# Delete Content-Length header so finalize() recalcs it.
response.headers.pop("Content-Length", None)
acceptable = cherrypy.request.headers.elements('Accept-Encoding')
if not acceptable:
# If no Accept-Encoding field is present in a request,
# the server MAY assume that the client will accept any
# content coding. In this case, if "identity" is one of
# the available content-codings, then the server SHOULD use
# the "identity" content-coding, unless it has additional
# information that a different content-coding is meaningful
# to the client.
return
ct = response.headers.get('Content-Type').split(';')[0]
ct = ct in cherrypy.config.get('gzip_filter.mime_types', ['text/html', 'text/plain'])
for coding in acceptable:
if coding.value == 'identity' and coding.qvalue != 0:
return
if coding.value in ('gzip', 'x-gzip'):
if coding.qvalue == 0:
return
if ct:
zipit()
return
cherrypy.HTTPError(406, "identity, gzip").set_response()
def write_gzip_header(self):
"""Adapted from the gzip.py standard module code"""
header = '\037\213' # magic header
header += '\010' # compression method
header += '\0'
header += struct.pack("<L", long(time.time()))
header += '\002'
header += '\377'
return header
def write_gzip_trailer(self, crc, size):
footer = struct.pack("<l", crc)
footer += struct.pack("<L", size & 0xFFFFFFFFL)
return footer
def zip_body(self, body, compress_level):
# Compress page
yield self.write_gzip_header()
crc = zlib.crc32("")
size = 0
zobj = zlib.compressobj(compress_level,
zlib.DEFLATED, -zlib.MAX_WBITS,
zlib.DEF_MEM_LEVEL, 0)
for line in body:
size += len(line)
crc = zlib.crc32(line, crc)
yield zobj.compress(line)
yield zobj.flush()
yield self.write_gzip_trailer(crc, size)
|