Commit 38a1be94 authored by Amos Latteier's avatar Amos Latteier

More fixes to streaming, chunking and keep-alive handling from Toby Dickenson. Toby you rock!

parent b8c3a39b
...@@ -105,7 +105,9 @@ import DebugLogger ...@@ -105,7 +105,9 @@ import DebugLogger
class ZServerHTTPResponse(HTTPResponse): class ZServerHTTPResponse(HTTPResponse):
"Used to push data into a channel's producer fifo" "Used to push data into a channel's producer fifo"
http_chunk=0 # Set this value to 1 if streaming output in
# HTTP/1.1 should use chunked encoding
http_chunk=1
http_chunk_size=1024 http_chunk_size=1024
# defaults # defaults
...@@ -113,12 +115,19 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -113,12 +115,19 @@ class ZServerHTTPResponse(HTTPResponse):
_http_connection='close' _http_connection='close'
_server_version='Zope/2.0 ZServer/2.0' _server_version='Zope/2.0 ZServer/2.0'
# using streaming response
_streaming=0 _streaming=0
# using chunking transfer-encoding
_chunking=0
def __str__(self, def __str__(self,
html_search=regex.compile('<html>',regex.casefold).search, html_search=regex.compile('<html>',regex.casefold).search,
): ):
if self._wrote: return '' # Streaming output was used. if self._wrote:
if self._chunking:
return '0\r\n\r\n'
else:
return ''
headers=self.headers headers=self.headers
body=self.body body=self.body
...@@ -146,15 +155,12 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -146,15 +155,12 @@ class ZServerHTTPResponse(HTTPResponse):
# and not streaming # and not streaming
if not headers.has_key('content-type') and \ if not headers.has_key('content-type') and \
not headers.has_key('content-length') and \ not headers.has_key('content-length') and \
not headers.has_key('transfer-encoding') and \
not self._streaming and \ not self._streaming and \
self.status == 200: self.status == 200:
self.setStatus('nocontent') self.setStatus('nocontent')
# add content length if not transfer encoded # add content length if not streaming
# and not streaming
if not headers.has_key('content-length') and \ if not headers.has_key('content-length') and \
not headers.has_key('transfer-encoding') and \
not self._streaming: not self._streaming:
self.setHeader('content-length',len(body)) self.setHeader('content-length',len(body))
...@@ -171,38 +177,25 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -171,38 +177,25 @@ class ZServerHTTPResponse(HTTPResponse):
# add zserver headers # add zserver headers
append('Server: %s' % self._server_version) append('Server: %s' % self._server_version)
append('Date: %s' % build_http_date(time.time())) append('Date: %s' % build_http_date(time.time()))
chunk=0
if self._http_version=='1.0': if self._http_version=='1.0':
if self._http_connection=='keep alive': if self._http_connection=='keep-alive' and \
if self.headers.has_key('content-length'): self.headers.has_key('content-length'):
self.setHeader('Connection','close') self.setHeader('Connection','Keep-Alive')
else:
self.setHeader('Connection','Keep-Alive')
else: else:
self.setHeader('Connection','close') self.setHeader('Connection','close')
elif self._http_version=='1.1':
# Close the connection if we have been asked to.
# Use chunking if streaming output.
if self._http_version=='1.1':
if self._http_connection=='close': if self._http_connection=='close':
self.setHeader('Connection','close') self.setHeader('Connection','close')
elif not self.headers.has_key('content-length'): elif not self.headers.has_key('content-length'):
if self.headers.has_key('transfer-encoding'): if self.http_chunk and self._streaming:
if self.headers['transfer-encoding'] != 'chunked':
self.setHeader('Connection','close')
else:
chunk=1
elif self.http_chunk:
self.setHeader('Transfer-Encoding','chunked') self.setHeader('Transfer-Encoding','chunked')
chunk=1 self._chunking=1
else: else:
self.setHeader('Connection','close') self.setHeader('Connection','close')
if chunk:
chunked_body=''
while body:
chunk=body[:self.http_chunk_size]
body=body[self.http_chunk_size:]
chunked_body='%s%x\r\n%s\r\n' % (chunked_body, len(chunk), chunk)
chunked_body='%s0\r\n\r\n' % chunked_body
body=chunked_body
for key, val in headers.items(): for key, val in headers.items():
if string.lower(key)==key: if string.lower(key)==key:
...@@ -257,6 +250,9 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -257,6 +250,9 @@ class ZServerHTTPResponse(HTTPResponse):
if not data: return if not data: return
if self._chunking:
data = '%x\r\n%s\r\n' % (len(data),data)
t=self._tempfile t=self._tempfile
if t is None: if t is None:
stdout.write(data) stdout.write(data)
......
...@@ -105,7 +105,9 @@ import DebugLogger ...@@ -105,7 +105,9 @@ import DebugLogger
class ZServerHTTPResponse(HTTPResponse): class ZServerHTTPResponse(HTTPResponse):
"Used to push data into a channel's producer fifo" "Used to push data into a channel's producer fifo"
http_chunk=0 # Set this value to 1 if streaming output in
# HTTP/1.1 should use chunked encoding
http_chunk=1
http_chunk_size=1024 http_chunk_size=1024
# defaults # defaults
...@@ -113,12 +115,19 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -113,12 +115,19 @@ class ZServerHTTPResponse(HTTPResponse):
_http_connection='close' _http_connection='close'
_server_version='Zope/2.0 ZServer/2.0' _server_version='Zope/2.0 ZServer/2.0'
# using streaming response
_streaming=0 _streaming=0
# using chunking transfer-encoding
_chunking=0
def __str__(self, def __str__(self,
html_search=regex.compile('<html>',regex.casefold).search, html_search=regex.compile('<html>',regex.casefold).search,
): ):
if self._wrote: return '' # Streaming output was used. if self._wrote:
if self._chunking:
return '0\r\n\r\n'
else:
return ''
headers=self.headers headers=self.headers
body=self.body body=self.body
...@@ -146,15 +155,12 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -146,15 +155,12 @@ class ZServerHTTPResponse(HTTPResponse):
# and not streaming # and not streaming
if not headers.has_key('content-type') and \ if not headers.has_key('content-type') and \
not headers.has_key('content-length') and \ not headers.has_key('content-length') and \
not headers.has_key('transfer-encoding') and \
not self._streaming and \ not self._streaming and \
self.status == 200: self.status == 200:
self.setStatus('nocontent') self.setStatus('nocontent')
# add content length if not transfer encoded # add content length if not streaming
# and not streaming
if not headers.has_key('content-length') and \ if not headers.has_key('content-length') and \
not headers.has_key('transfer-encoding') and \
not self._streaming: not self._streaming:
self.setHeader('content-length',len(body)) self.setHeader('content-length',len(body))
...@@ -171,38 +177,25 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -171,38 +177,25 @@ class ZServerHTTPResponse(HTTPResponse):
# add zserver headers # add zserver headers
append('Server: %s' % self._server_version) append('Server: %s' % self._server_version)
append('Date: %s' % build_http_date(time.time())) append('Date: %s' % build_http_date(time.time()))
chunk=0
if self._http_version=='1.0': if self._http_version=='1.0':
if self._http_connection=='keep alive': if self._http_connection=='keep-alive' and \
if self.headers.has_key('content-length'): self.headers.has_key('content-length'):
self.setHeader('Connection','close') self.setHeader('Connection','Keep-Alive')
else:
self.setHeader('Connection','Keep-Alive')
else: else:
self.setHeader('Connection','close') self.setHeader('Connection','close')
elif self._http_version=='1.1':
# Close the connection if we have been asked to.
# Use chunking if streaming output.
if self._http_version=='1.1':
if self._http_connection=='close': if self._http_connection=='close':
self.setHeader('Connection','close') self.setHeader('Connection','close')
elif not self.headers.has_key('content-length'): elif not self.headers.has_key('content-length'):
if self.headers.has_key('transfer-encoding'): if self.http_chunk and self._streaming:
if self.headers['transfer-encoding'] != 'chunked':
self.setHeader('Connection','close')
else:
chunk=1
elif self.http_chunk:
self.setHeader('Transfer-Encoding','chunked') self.setHeader('Transfer-Encoding','chunked')
chunk=1 self._chunking=1
else: else:
self.setHeader('Connection','close') self.setHeader('Connection','close')
if chunk:
chunked_body=''
while body:
chunk=body[:self.http_chunk_size]
body=body[self.http_chunk_size:]
chunked_body='%s%x\r\n%s\r\n' % (chunked_body, len(chunk), chunk)
chunked_body='%s0\r\n\r\n' % chunked_body
body=chunked_body
for key, val in headers.items(): for key, val in headers.items():
if string.lower(key)==key: if string.lower(key)==key:
...@@ -257,6 +250,9 @@ class ZServerHTTPResponse(HTTPResponse): ...@@ -257,6 +250,9 @@ class ZServerHTTPResponse(HTTPResponse):
if not data: return if not data: return
if self._chunking:
data = '%x\r\n%s\r\n' % (len(data),data)
t=self._tempfile t=self._tempfile
if t is None: if t is None:
stdout.write(data) stdout.write(data)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment