Changeset 95
- Timestamp:
- 12/29/04 08:42:47
- Files:
-
- trunk/cherrypy/_cphttptools.py (modified) (3 diffs)
- trunk/cherrypy/lib/filter/basefilter.py (modified) (1 diff)
- trunk/cherrypy/lib/filter/baseurlfilter.py (modified) (1 diff)
- trunk/cherrypy/lib/filter/encodingfilter.py (modified) (1 diff)
- trunk/cherrypy/lib/filter/gzipfilter.py (modified) (3 diffs)
- trunk/cherrypy/lib/filter/logdebuginfofilter.py (modified) (3 diffs)
- trunk/cherrypy/lib/filter/tidyfilter.py (modified) (3 diffs)
- trunk/cherrypy/lib/filter/xmlrpcfilter.py (copied) (copied from branches/ticket-59/cherrypy/lib/filter/xmlrpcfilter.py)
- trunk/cherrypy/test/testFilter1.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cphttptools.py
r81 r95 235 235 236 236 # Set the content-length 237 if cpg.response.headerMap.has_key('Content-Length') and cpg.response.headerMap['Content-Length']==0: 238 cpg.response.headerMap['Content-Length'] = len(cpg.response.body) 237 if (cpg.response.headerMap.has_key('Content-Length') and 238 cpg.response.headerMap['Content-Length']==0): 239 #body = "" 240 #body = ''.join(list(cpg.response.body)) # a local var is more efficient here 241 #body = u''.join(cpg.response.body) # a local var is more efficient here 242 #body = '' 243 #for line in cpg.response.body: 244 # print body 245 # body += line 246 buf = StringIO.StringIO() 247 [buf.write(x) for x in cpg.response.body] 248 buf.seek(0) 249 cpg.response.body = [buf.read()] 250 cpg.response.headerMap['Content-Length'] = len(cpg.response.body[0]) 239 251 240 252 wfile.write('%s %s\r\n' % (cpg.response.headerMap['protocolVersion'], cpg.response.headerMap['Status'])) … … 251 263 wfile.write('\r\n') 252 264 253 applyFilterList('afterResponseHeader') 254 255 applyFilterList('beforeResponseFullBody') 256 257 # Check that the response body is a string 258 if type(cpg.response.body) != types.StringType: 259 raise cperror.WrongResponseType 260 261 wfile.write(cpg.response.body) 265 for line in cpg.response.body: 266 wfile.write(line) 267 268 # finalization hook for filter cleanup & logging purposes 269 applyFilterList('afterResponse') 262 270 263 271 def handleRequest(wfile): … … 363 371 # Remove "root" from objectPathList and join it to get objectPath 364 372 cpg.request.objectPath = '/' + '/'.join(objectPathList[1:]) 365 cpg.response.body = func(*(virtualPathList + cpg.request.paramList), **(cpg.request.paramMap)) 373 body = func(*(virtualPathList + cpg.request.paramList), **(cpg.request.paramMap)) 374 375 # builds a uniform return type 376 if not isinstance(body, types.GeneratorType): 377 cpg.response.body = [body] 378 else: 379 cpg.response.body = body 366 380 367 381 if cpg.response.sendResponse: trunk/cherrypy/lib/filter/basefilter.py
r81 r95 36 36 pass 37 37 38 def afterResponse Header(self):39 """ Called after writing the response header"""38 def afterResponse(self): 39 """ Called after writing the response (header & body included) """ 40 40 pass 41 41 42 def beforeResponseFullBody(self):43 """ Called before writing the full response body """44 pass45 46 def beforeResponseOnTheFlyBody(self):47 """ Called before writing a bit of the reponse (only used48 when using "on-the-fly" response.49 """50 pass51 trunk/cherrypy/lib/filter/baseurlfilter.py
r72 r95 31 31 else: 32 32 newBaseUrl = self.baseUrl 33 if newBaseUrl.find("://") == -1:34 # add http:// or https:// if needed35 newBaseUrl = cpg.request.base[:cpg.request.base.find("://")] + "://" + newBaseUrl33 if newBaseUrl.find("://") == -1: 34 # add http:// or https:// if needed 35 newBaseUrl = cpg.request.base[:cpg.request.base.find("://")] + "://" + newBaseUrl 36 36 37 37 cpg.request.browserUrl = cpg.request.browserUrl.replace( trunk/cherrypy/lib/filter/encodingfilter.py
r41 r95 21 21 """ 22 22 23 def __init__(self, encoding = 'utf-8' ):23 def __init__(self, encoding = 'utf-8', mimeTypeList = ['text/html']): 24 24 self.encoding = encoding 25 self.mimeTypeList = mimeTypeList 25 26 26 27 def beforeResponse(self): 27 if isinstance(cpg.response.body, unicode): 28 # Encode the response 29 cpg.response.body = cpg.response.body.encode(self.encoding) 28 ct = cpg.response.headerMap.get('Content-Type').split(';')[0] 29 if (ct in self.mimeTypeList): 30 30 # Add "charset=..." to response Content-Type header 31 31 contentType = cpg.response.headerMap.get("Content-Type") 32 32 if contentType and 'charset' not in contentType: 33 cpg.response.headerMap["Content-Type"] += "; charset=%s" % self.encoding 33 cpg.response.headerMap["Content-Type"] += ";charset=%s" % self.encoding 34 # Return a generator that encodes the sequence 35 cpg.response.body = self.encode_body(cpg.response.body) 34 36 37 def encode_body(self, body): 38 for line in body: 39 yield line.encode(self.encoding) trunk/cherrypy/lib/filter/gzipfilter.py
r64 r95 12 12 """ 13 13 14 import gzip, StringIO 14 import zlib 15 import struct 16 import time 15 17 from basefilter import BaseOutputFilter 16 18 from cherrypy import cpg … … 21 23 """ 22 24 23 def __init__(self, mimeTypeList = ['text/html'] ):25 def __init__(self, mimeTypeList = ['text/html'], compresslevel=9): 24 26 # List of mime-types to compress 25 27 self.mimeTypeList = mimeTypeList 28 self.compresslevel = compresslevel 26 29 27 30 def beforeResponse(self): … … 34 37 # Set header 35 38 cpg.response.headerMap['Content-Encoding'] = 'gzip' 36 # Compress page 37 zbuf = StringIO.StringIO() 38 zfile = gzip.GzipFile(mode='wb', fileobj = zbuf, compresslevel = 9) 39 zfile.write(cpg.response.body) 40 zfile.close() 41 cpg.response.body = zbuf.getvalue() 39 # Return a generator that compresses the page 40 cpg.response.body = self.zip_body(cpg.response.body) 42 41 42 def write_gzip_header(self): 43 """ 44 Adapted from the gzip.py standard module code 45 """ 46 header = '\037\213' # magic header 47 header += '\010' # compression method 48 header += '\0' 49 header += struct.pack("<L", long(time.time())) 50 header += '\002' 51 header += '\377' 52 return header 53 54 def write_gzip_trailer(self, crc, size): 55 footer = struct.pack("<l", crc) 56 footer += struct.pack("<L", size & 0xFFFFFFFFL) 57 return footer 43 58 59 def zip_body(self, body): 60 # Compress page 61 yield self.write_gzip_header() 62 crc = zlib.crc32("") 63 size = 0 64 zobj = zlib.compressobj(self.compresslevel, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0) 65 for line in body: 66 size += len(line) 67 crc = zlib.crc32(line, crc) 68 yield zobj.compress(line) 69 yield zobj.flush() 70 yield self.write_gzip_trailer(crc, size) trunk/cherrypy/lib/filter/logdebuginfofilter.py
r41 r95 15 15 from basefilter import BaseInputFilter, BaseOutputFilter 16 16 from cherrypy import cpg 17 from itertools import chain 17 18 18 19 class LogDebugInfoStartFilter(BaseInputFilter, BaseOutputFilter): … … 38 39 ct = cpg.response.headerMap.get('Content-Type') 39 40 if (ct in self.mimeTypeList): 41 debuginfo = '\n' 40 42 if self.logAsComment: 41 cpg.response.body+= '<!-- '43 debuginfo += '<!-- ' 42 44 else: 43 cpg.response.body+= self.preTag45 debuginfo += self.preTag 44 46 logList = [] 45 47 if self.logBuildTime: … … 58 60 len(dumpStr)/float(1024))) 59 61 60 cpg.response.body+= ', '.join(logList)62 debuginfo += ', '.join(logList) 61 63 if self.logAsComment: 62 cpg.response.body+= '-->'64 debuginfo += '-->' 63 65 64 if 'Content-Length' in cpg.response.headerMap: 65 cpg.response.headerMap['Content-Length'] = len(cpg.response.body) 66 66 cpg.response.body = chain(cpg.response.body, [debuginfo]) trunk/cherrypy/lib/filter/tidyfilter.py
r40 r95 31 31 32 32 def beforeResponse(self): 33 # the tidy filter, by its very nature it's not generator friendly, 34 # so we just collect the body and work with it. 35 originalBody = ''.join(cpg.response.body) 36 33 37 ct = cpg.response.headerMap.get('Content-Type') 34 38 if ct == 'text/html': … … 37 41 errFile = os.path.join(self.tmpDir, 'tidy.err') 38 42 f = open(pageFile, 'wb') 39 f.write( cpg.response.body)43 f.write(originalBody) 40 44 f.close() 41 45 encoding = cpg.response.headerMap.get('Content-Encoding', '') … … 60 64 61 65 if newErrList: 62 oldHtml = cpg.response.body 63 cpg.response.body = "Wrong HTML:<br>" + cgi.escape('\n'.join(newErrList)).replace('\n','<br>') 64 cpg.response.body += '<br><br>' 66 newBody = "Wrong HTML:<br>" + cgi.escape('\n'.join(newErrList)).replace('\n','<br>') 67 newBody += '<br><br>' 65 68 i=0 66 69 for line in oldHtml.splitlines(): 67 70 i += 1 68 cpg.response.body += "%03d - "%i + cgi.escape(line).replace('\t',' ').replace(' ',' ') + '<br>'71 newBody += "%03d - "%i + cgi.escape(line).replace('\t',' ').replace(' ',' ') + '<br>' 69 72 70 cpg.response. headerMap['Content-Length'] = len(cpg.response.body)73 cpg.response.body = [newBody] trunk/cherrypy/test/testFilter1.py
r16 r95 15 15 code = r""" 16 16 from cherrypy import cpg 17 import cherrypy.lib.filter.gzipfilter as gzipfilter 18 import cherrypy.lib.filter.encodingfilter as encodingfilter 19 import cherrypy.lib.filter.generatorfilter as generatorfilter 17 from cherrypy.lib.filter.gzipfilter import GzipFilter 18 from cherrypy.lib.filter.encodingfilter import EncodingFilter 20 19 europoundUnicode = u'\x80\xa3' 21 20 class Root: 22 21 _cpFilterList = [ 23 generatorfilter.GeneratorFilter(), 24 encodingfilter.EncodingFilter(), 25 gzipfilter.GzipFilter() 22 EncodingFilter(), 23 GzipFilter() 26 24 ] 27 25 def index(self): … … 49 47 # Gzip compression doesn't always return the same exact result ! 50 48 # So we just check that the first few bytes are the same 51 helper.checkPageResult(' Object mapping', infoMap, code, testList, failedList, extraRequestHeader = [("Accept-Encoding", "gzip")])49 helper.checkPageResult('Filters', infoMap, code, testList, failedList, extraRequestHeader = [("Accept-Encoding", "gzip")])

