<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:courier, monaco, monospace, sans-serif;font-size:12pt"><DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">Thanks.</DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">&nbsp;</DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">So it seems I have to write my own code, there in nothing like I can set some flag.</DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">&nbsp;</DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">So if that is the case shouldn't I just be gzipping and unzipping data write and read to request object.</DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">&nbsp;</DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">rgds</DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif">anurag<BR><BR></DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: times new roman, new york, times, serif">----- Original Message ----<BR>From: David Bolen &lt;db3l.net@gmail.com&gt;<BR>To: twisted-python@twistedmatrix.com<BR>Sent: Friday, October 19, 2007 1:02:21 AM<BR>Subject: [Twisted-Python] Re: Content Encoding : gzip ?<BR><BR>
<DIV>anurag uniyal &lt;anuraguniyal@yahoo.com&gt; writes:<BR><BR>&gt; Is it possible to send and recieve compressed content using twisted.web?<BR>&gt;<BR>&gt; I have set Accept-encoding to gzip but it doesn't make any difference.<BR>&gt; Will I have to cater for this myself?<BR><BR>Yes, in twisted.web.&nbsp;&nbsp;In twisted.web2, there's a filter that supports it.<BR><BR>Here's a small wrapper class I wrote recently that I've used to handle<BR>this in twisted.web, with the goal of minimal changes to existing<BR>resource code.&nbsp;&nbsp;I use it by noticing, in the original request handler,<BR>the ability to handle gzip encodings, and then wrap the original<BR>request in this class (since there's no built-in filtering of the<BR>output stream in twisted.web).<BR><BR>It's worked fine in my tests to date, and in limited production use,<BR>but to be honest it hasn't seen large scale, long term use because my<BR>original use case only yielded ~15% compression
 (multimedia files) and<BR>using this negates the ability to know the full length in advance,<BR>thus clients can't give projected download times.&nbsp;&nbsp;(My files are large<BR>enough that compressing twice is high overhead, and it wouldn't play<BR>well with the wrapper approach anyway).<BR><BR>In any event, hopefully it'll be a useful starting point for you.<BR><BR>Here's the wrapper:<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- - - - - - - - - - - - - - - - - - - - - - - - -<BR><BR>import struct<BR>import zlib<BR><BR>class GzipRequest(object):<BR>&nbsp;&nbsp;&nbsp;&nbsp;"""Wrapper for a request that applies a gzip content encoding"""<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;def __init__(self, request, compressLevel=6):<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request = request<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request.setHeader('Content-Encoding',
 'gzip')<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Borrowed from twisted.web2 gzip filter<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.compress = zlib.compressobj(compressLevel, zlib.DEFLATED,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL,0)<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;def __getattr__(self, attr):<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if 'request' in self.__dict__:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return getattr(self.request, attr)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise AttributeError, attr<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;def __setattr__(self, attr,
 value):<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if 'request' in self.__dict__:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return setattr(self.request, attr, value)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__dict__[attr] = value<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;def write(self, data):<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not self.request.startedWriting:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.crc = zlib.crc32('')<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.size = self.csize = 0<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# XXX: Zap any length for now since we don't know final size<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if 'content-length' in
 self.request.headers:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;del self.request.headers['content-length']<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Borrow header information from twisted.web2 gzip filter<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request.write('\037\213\010\000' '\0\0\0\0' '\002\377')<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.crc = zlib.crc32(data, self.crc)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.size += len(data)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cdata = self.compress.compress(data)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.csize += len(cdata)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if
 cdata:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request.write(cdata)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elif self.request.producer:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Simulate another pull even though it hasn't really made it<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# out to the consumer yet.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request.producer.resumeProducing()<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;def finish(self):<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remain = self.compress.flush()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.csize += len(remain)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if
 remain:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request.write(remain)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request.write(struct.pack('&lt;LL',<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.crc &amp; 0xFFFFFFFFL,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.size &amp; 0xFFFFFFFFL))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.request.finish()<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- - - - - - - - - - - - - - - - - - - - - - - - -<BR><BR>and here's a sample of using
 it.&nbsp;&nbsp;This code is from one of my Resource<BR>objects - if I were to use it more generally in my site I'd extract that<BR>into a mix-in class of some sort - currently there was only one specific<BR>resource (the multimedia files) I wanted to support it for:<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;def render_GET(self, request):<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# (... argument validation ...)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accept_encoding = request.getHeader('accept-encoding')<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if accept_encoding:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;encodings = accept_encoding.split(',')<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for encoding in encodings:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name =
 encoding.split(';')[0].strip()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if name == 'gzip':<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request = GzipRequest(request)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# At this point, use 'request' as normal<BR><BR><BR>-- David<BR><BR><BR>_______________________________________________<BR>Twisted-Python mailing list<BR>Twisted-Python@twistedmatrix.com<BR><A href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python" target=_blank>http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</A></DIV></DIV>
<DIV style="FONT-SIZE: 12pt; FONT-FAMILY: courier, monaco, monospace, sans-serif"><BR></DIV></div><br>__________________________________________________<br>Do You Yahoo!?<br>Tired of spam?  Yahoo! Mail has the best spam protection around <br>http://mail.yahoo.com </body></html>