Changeset 1964
- Timestamp:
- 05/24/08 00:49:43
- Files:
-
- branches/sendfile/cherrypy/_cptools.py (modified) (1 diff)
- branches/sendfile/cherrypy/_cpwsgi.py (modified) (2 diffs)
- branches/sendfile/cherrypy/lib/static.py (modified) (1 diff)
- branches/sendfile/cherrypy/test/benchmark.py (modified) (1 diff)
- branches/sendfile/cherrypy/wsgiserver/__init__.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/sendfile/cherrypy/_cptools.py
r1960 r1964 156 156 157 157 def _wrapper(self, **kwargs): 158 """If self.callable returns True, turn off any other handler.""" 158 159 if self.callable(**kwargs): 159 160 cherrypy.request.handler = None branches/sendfile/cherrypy/_cpwsgi.py
r1938 r1964 123 123 s, h, b = _cperror.bare_error() 124 124 self.iter_response = iter(b) 125 126 if isinstance(b, self.environ['wsgi.file_wrapper']): 127 self.file_response = b 125 128 126 129 def iredirect(self, path, query_string): … … 298 301 so that any WSGI middleware in self.pipeline can run first. 299 302 """ 300 return self.response_class(environ, start_response, self.cpapp) 303 r_iter = self.response_class(environ, start_response, self.cpapp) 304 if getattr(r_iter, 'file_response', None) is not None: 305 # Return the file_wrapper object directly instead 306 return r_iter.file_response 307 return r_iter 301 308 302 309 def __call__(self, environ, start_response): branches/sendfile/cherrypy/lib/static.py
r1957 r1964 68 68 69 69 # Set Content-Length and use an iterable (file object) 70 # this way CP won't load the whole file in memory 70 # this way CP won't load the whole file in memory 71 # (assuming response.stream is True and no other 72 # code collapses the body). 71 73 c_len = st.st_size 72 74 bodyfile = open(path, 'rb') 75 fw = getattr(cherrypy.request, 'wsgi_environ', {}).get('wsgi.file_wrapper') 76 if fw is not None: 77 # TODO: support Content-Range 78 response.headers['Content-Length'] = c_len 79 response.body = fw(bodyfile) 80 print ".", 81 return response.body 73 82 74 83 # HTTP/1.0 didn't have Range/Accept-Ranges headers, or the 206 code branches/sendfile/cherrypy/test/benchmark.py
r1908 r1964 286 286 287 287 print 288 print ("Client Thread Report (1000 requests, 1 4bytes via staticdir, "288 print ("Client Thread Report (1000 requests, 1500 bytes via staticdir, " 289 289 "%s server threads):" % cherrypy.server.thread_pool) 290 print_report(thread_report("%s/static/index .html" % SCRIPT_NAME))291 292 print293 print ("Size Report (1000 requests, 50 client threads, "294 "%s server threads):" % cherrypy.server.thread_pool)295 print_report(size_report())290 print_report(thread_report("%s/static/index2.html" % SCRIPT_NAME)) 291 292 # print 293 # print ("Size Report (1000 requests, 50 client threads, " 294 # "%s server threads):" % cherrypy.server.thread_pool) 295 # print_report(size_report()) 296 296 297 297 branches/sendfile/cherrypy/wsgiserver/__init__.py
r1961 r1964 546 546 response = self.wsgi_app(self.environ, self.start_response) 547 547 try: 548 for chunk in response: 549 # "The start_response callable must not actually transmit 550 # the response headers. Instead, it must store them for the 551 # server or gateway to transmit only after the first 552 # iteration of the application return value that yields 553 # a NON-EMPTY string, or upon the application's first 554 # invocation of the write() callable." (PEP 333) 555 if chunk: 556 self.write(chunk) 548 if isinstance(response, FileWrapper) and hasattr(response, '_transmit'): 549 if not self.sent_headers: 550 self.sent_headers = True 551 self.send_headers() 552 # TODO: support chunked write 553 response._transmit(self.wfile._sock) 554 else: 555 for chunk in response: 556 # "The start_response callable must not actually transmit 557 # the response headers. Instead, it must store them for the 558 # server or gateway to transmit only after the first 559 # iteration of the application return value that yields 560 # a NON-EMPTY string, or upon the application's first 561 # invocation of the write() callable." (PEP 333) 562 if chunk: 563 self.write(chunk) 557 564 finally: 558 565 if hasattr(response, "close"): … … 1540 1547 self.environ.update(ssl_environ) 1541 1548 1549 class FileWrapper(object): 1550 1551 def __init__(self, filelike, blksize=8192): 1552 self.filelike = filelike 1553 self.blksize = blksize 1554 1555 def close(self): 1556 if hasattr(self.filelike, 'close'): 1557 self.filelike.close() 1558 1559 def __iter__(self): 1560 return self 1561 1562 def next(self): 1563 data = self.filelike.read(self.blksize) 1564 if data: 1565 return data 1566 raise StopIteration 1567 #HTTPConnection.environ['wsgi.file_wrapper'] = FileWrapper 1568 1569 try: 1570 import sendfile 1571 except ImportError: 1572 pass 1573 else: 1574 class SendFileWrapper(FileWrapper): 1575 1576 def _transmit(self, socket): 1577 fd = self.filelike.fileno() 1578 filelen = os.fstat(fd).st_size 1579 offset = 0 1580 while offset < filelen: 1581 try: 1582 pos, sent = sendfile.sendfile( 1583 socket.fileno(), fd, offset, 1584 self.blksize) 1585 offset += sent 1586 except socket.error, e: 1587 if e.args[0] not in socket_errors_nonblocking: 1588 raise 1589 print format_exc() 1590 # HTTPConnection.environ['wsgi.file_wrapper'] = SendFileWrapper 1591 1592

