mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
handle TE: chunked .
This commit is contained in:
parent
6f5b16ab91
commit
ccd24a15ae
@ -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)
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user