handle TE: chunked .

This commit is contained in:
Benoit Chesneau 2010-01-18 14:58:36 +01:00
parent 6f5b16ab91
commit ccd24a15ae
3 changed files with 45 additions and 40 deletions

View File

@ -30,7 +30,10 @@ class HttpParser(object):
self.version = None
self.method = None
self.path = None
self._content_len = None
self._content_len = None
self.start_offset = 0
self.chunk_size = 0
self._chunk_eof = False
def headers(self, headers, buf):
""" take a string buff. It return
@ -121,22 +124,39 @@ class HttpParser(object):
def body_eof(self):
"""do we have all the body ?"""
#TODO : add chunk
if self.is_chunked and self._chunk_eof:
return True
if self._content_len == 0:
return True
return False
def read_chunk(self, data):
dlen = len(data)
i = data.find("\n")
if i != -1:
chunk = data[:i].strip().split(";", 1)
chunk_size = int(line.pop(0), 16)
if chunk_size <= 0:
self._chunk_eof = True
return None
self.start_offset = i+1
if not self.start_offset:
i = data.find("\n")
if i != -1:
chunk = data[:i].strip().split(";", 1)
chunk_size = int(line.pop(0), 16)
self.start_offset = i+1
self.chunk_size = chunk_size
else:
buf = self.data[self.start_offset:]
end_offset = chunk_size + 2
# we wait CRLF else return None
if len(buf) == end_offset:
if chunk_size <= 0:
self._chunk_eof = True
# we put data
return None, data[:end_offset]
self.chunk_size = 0
return buf[chunk_size:], data[:end_offset]
return None, data
def trailing_header(self, data):
i = data.find("\r\n\r\n")
return (i != -1)
def filter_body(self, data):
""" filter body and return a tuple:
body_chunk, new_buffer. They could be None.
@ -146,7 +166,9 @@ class HttpParser(object):
dlen = len(data)
chunk = None
if self.is_chunked:
pass
chunk, data = self.read_chunk(data)
if not chunk:
return None, data
else:
if self._content_len > 0:
nr = min(dlen, self._content_len)

View File

@ -102,10 +102,7 @@ class HTTPRequest(object):
wsgi_input = StringIO.StringIO()
else:
wsgi_input = TeeInput(self.socket, self.parser, buf)
environ = {
"wsgi.url_scheme": 'http',
"wsgi.input": wsgi_input,
@ -135,29 +132,6 @@ class HTTPRequest(object):
environ[key] = value
return environ
def decode_chunked(self):
"""Decode the 'chunked' transfer coding."""
length = 0
data = StringIO.StringIO()
while True:
line = self.io.readuntil("\n").strip().split(";", 1)
chunk_size = int(line.pop(0), 16)
if chunk_size <= 0:
break
length += chunk_size
data.write(self.io.recv(chunk_size))
crlf = self.io.read(2)
if crlf != "\r\n":
raise RequestError((400, "Bad chunked transfer coding "
"(expected '\\r\\n', got %r)" % crlf))
return
# Grab any trailer headers
self.read_headers()
data.seek(0)
return data, str(length) or ""
def start_response(self, status, response_headers):
self.response_status = status
for name, value in response_headers:

View File

@ -69,7 +69,9 @@ class TeeInput(object):
self._len = self._tmp_size()
return self._len
def flush(self):
self.tmp.flush()
def read(self, length=None):
""" read """
if not self.socket:
@ -148,6 +150,13 @@ class TeeInput(object):
""" here we wil fetch final trailers
if any."""
if self.parser.body_eof():
# handle trailing headers
if self.parser.is_chunked:
while not self.parser.trailing_header(self.buf):
data = read_partial(self.socket, CHUNK_SIZE)
if not data: break
self.buf += data
del self.buf
self.socket = None
def _tmp_size(self):