69 lines
2.5 KiB
Python
69 lines
2.5 KiB
Python
import struct
|
|
import zlib
|
|
from twisted.web.static import File
|
|
|
|
class GzipFile(File):
|
|
def render_GET(self, request):
|
|
request = GzipRequest(request)
|
|
return File.render_GET(self, request)
|
|
|
|
class GzipRequest(object):
|
|
"""Wrapper for a request that applies a gzip content encoding"""
|
|
|
|
def __init__(self, request, compressLevel=6):
|
|
self.request = request
|
|
self.request.setHeader('Content-Encoding', 'gzip')
|
|
# Borrowed from twisted.web2 gzip filter
|
|
self.compress = zlib.compressobj(compressLevel, zlib.DEFLATED,
|
|
-zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL,0)
|
|
|
|
def __getattr__(self, attr):
|
|
if 'request' in self.__dict__:
|
|
return getattr(self.request, attr)
|
|
else:
|
|
raise AttributeError, attr
|
|
|
|
def __setattr__(self, attr, value):
|
|
if 'request' in self.__dict__:
|
|
return setattr(self.request, attr, value)
|
|
else:
|
|
self.__dict__[attr] = value
|
|
|
|
def write(self, data):
|
|
if not self.request.startedWriting:
|
|
#print 'GzipRequest: Initializing'
|
|
self.crc = zlib.crc32('')
|
|
self.size = self.csize = 0
|
|
# XXX: Zap any length for now since we don't know final size
|
|
if 'content-length' in self.request.headers:
|
|
del self.request.headers['content-length']
|
|
# Borrow header information from twisted.web2 gzip filter
|
|
self.request.write('\037\213\010\000' '\0\0\0\0' '\002\377')
|
|
|
|
self.crc = zlib.crc32(data, self.crc)
|
|
self.size += len(data)
|
|
cdata = self.compress.compress(data)
|
|
self.csize += len(cdata)
|
|
'''
|
|
print 'GzipRequest: ' \
|
|
'Writing %d bytes, %d total (%d compressed, %d total)' % \
|
|
(len(data),self.size,len(cdata),self.csize)
|
|
'''
|
|
if cdata:
|
|
self.request.write(cdata)
|
|
elif self.request.producer:
|
|
# Simulate another pull even though it hasn't really made it
|
|
# out to the consumer yet.
|
|
self.request.producer.resumeProducing()
|
|
|
|
def finish(self):
|
|
remain = self.compress.flush()
|
|
self.csize += len(remain)
|
|
#print 'GzipRequest: Finishing (size %d, compressed %d)' % (self.size, self.csize)
|
|
if remain:
|
|
self.request.write(remain)
|
|
self.request.write(struct.pack('<LL',
|
|
self.crc & 0xFFFFFFFFL,
|
|
self.size & 0xFFFFFFFFL))
|
|
self.request.finish()
|