mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
new read_partial function. We also now use buffer in parser.
This commit is contained in:
parent
05d4673972
commit
d92364af71
@ -12,4 +12,4 @@ def app(environ, start_response):
|
|||||||
('Content-Length', str(len(data)))
|
('Content-Length', str(len(data)))
|
||||||
]
|
]
|
||||||
start_response(status, response_headers)
|
start_response(status, response_headers)
|
||||||
return [data]
|
return iter([data])
|
||||||
|
|||||||
@ -38,10 +38,11 @@ class Parser(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
ld = len("\r\n\r\n")
|
ld = len("\r\n\r\n")
|
||||||
i = buf.find("\r\n\r\n")
|
s = "".join(buf)
|
||||||
|
i = s.find("\r\n\r\n")
|
||||||
if i != -1:
|
if i != -1:
|
||||||
if i > 0:
|
if i > 0:
|
||||||
r = buf[:i]
|
r = s[:i]
|
||||||
pos = i+ld
|
pos = i+ld
|
||||||
return self.finalize_headers(headers, r, pos)
|
return self.finalize_headers(headers, r, pos)
|
||||||
return -1
|
return -1
|
||||||
@ -144,10 +145,11 @@ class Parser(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def read_chunk(self, data):
|
def read_chunk(self, data):
|
||||||
|
s = "".join(data)
|
||||||
if not self.start_offset:
|
if not self.start_offset:
|
||||||
i = data.find("\r\n")
|
i = s.find("\r\n")
|
||||||
if i != -1:
|
if i != -1:
|
||||||
chunk = data[:i].strip().split(";", 1)
|
chunk = s[:i].strip().split(";", 1)
|
||||||
chunk_size = int(chunk.pop(0), 16)
|
chunk_size = int(chunk.pop(0), 16)
|
||||||
self.start_offset = i+2
|
self.start_offset = i+2
|
||||||
self.chunk_size = chunk_size
|
self.chunk_size = chunk_size
|
||||||
@ -158,17 +160,18 @@ class Parser(object):
|
|||||||
ret = '', data[:self.start_offset]
|
ret = '', data[:self.start_offset]
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
buf = data[self.start_offset:self.start_offset+self.chunk_size]
|
chunk = s[self.start_offset:self.start_offset+self.chunk_size]
|
||||||
end_offset = self.start_offset + self.chunk_size + 2
|
end_offset = self.start_offset + self.chunk_size + 2
|
||||||
# we wait CRLF else return None
|
# we wait CRLF else return None
|
||||||
if len(data) >= end_offset:
|
if len(data) >= end_offset:
|
||||||
ret = buf, data[end_offset:]
|
ret = chunk, data[end_offset:]
|
||||||
self.chunk_size = 0
|
self.chunk_size = 0
|
||||||
return ret
|
return ret
|
||||||
return '', data
|
return '', data
|
||||||
|
|
||||||
def trailing_header(self, data):
|
def trailing_header(self, data):
|
||||||
i = data.find("\r\n\r\n")
|
s = "".join(data)
|
||||||
|
i = s.find("\r\n\r\n")
|
||||||
return (i != -1)
|
return (i != -1)
|
||||||
|
|
||||||
def filter_body(self, data):
|
def filter_body(self, data):
|
||||||
@ -179,17 +182,15 @@ class Parser(object):
|
|||||||
dlen = len(data)
|
dlen = len(data)
|
||||||
chunk = ''
|
chunk = ''
|
||||||
if self.is_chunked:
|
if self.is_chunked:
|
||||||
|
|
||||||
chunk, data = self.read_chunk(data)
|
chunk, data = self.read_chunk(data)
|
||||||
|
|
||||||
if not chunk:
|
if not chunk:
|
||||||
return '', data
|
return '', data
|
||||||
else:
|
else:
|
||||||
if self._content_len > 0:
|
if self._content_len > 0:
|
||||||
nr = min(dlen, self._content_len)
|
nr = min(dlen, self._content_len)
|
||||||
chunk = data[:nr]
|
chunk = "".join(data[:nr])
|
||||||
self._content_len -= nr
|
self._content_len -= nr
|
||||||
data = ''
|
data = []
|
||||||
|
|
||||||
self.start_offset = 0
|
self.start_offset = 0
|
||||||
return (chunk, data)
|
return (chunk, data)
|
||||||
|
|||||||
@ -55,7 +55,6 @@ class Request(object):
|
|||||||
def read(self):
|
def read(self):
|
||||||
environ = {}
|
environ = {}
|
||||||
headers = []
|
headers = []
|
||||||
buf = ""
|
|
||||||
buf = read_partial(self.socket, CHUNK_SIZE)
|
buf = read_partial(self.socket, CHUNK_SIZE)
|
||||||
i = self.parser.filter_headers(headers, buf)
|
i = self.parser.filter_headers(headers, buf)
|
||||||
if i == -1 and buf:
|
if i == -1 and buf:
|
||||||
@ -64,7 +63,8 @@ class Request(object):
|
|||||||
if not data: break
|
if not data: break
|
||||||
buf += data
|
buf += data
|
||||||
i = self.parser.filter_headers(headers, buf)
|
i = self.parser.filter_headers(headers, buf)
|
||||||
if i != -1: break
|
if i != -1:
|
||||||
|
break
|
||||||
|
|
||||||
self.log.debug("%s", self.parser.status)
|
self.log.debug("%s", self.parser.status)
|
||||||
self.log.debug("Headers:\n%s" % headers)
|
self.log.debug("Headers:\n%s" % headers)
|
||||||
|
|||||||
@ -129,6 +129,8 @@ class TeeInput(object):
|
|||||||
def _tee(self, length):
|
def _tee(self, length):
|
||||||
""" fetch partial body"""
|
""" fetch partial body"""
|
||||||
while True:
|
while True:
|
||||||
|
self.buf = read_partial(self.socket, length, self.buf)
|
||||||
|
|
||||||
chunk, self.buf = self.parser.filter_body(self.buf)
|
chunk, self.buf = self.parser.filter_body(self.buf)
|
||||||
if chunk:
|
if chunk:
|
||||||
fwrite(self.tmp, chunk)
|
fwrite(self.tmp, chunk)
|
||||||
@ -137,8 +139,6 @@ class TeeInput(object):
|
|||||||
if self.parser.body_eof():
|
if self.parser.body_eof():
|
||||||
break
|
break
|
||||||
|
|
||||||
data = read_partial(self.socket, length)
|
|
||||||
self.buf += data
|
|
||||||
self._finalize()
|
self._finalize()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
# This file is part of gunicorn released under the MIT license.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
|
import array
|
||||||
import ctypes
|
import ctypes
|
||||||
import errno
|
import errno
|
||||||
import fcntl
|
import fcntl
|
||||||
@ -92,8 +93,13 @@ def close(sock):
|
|||||||
except socket.error:
|
except socket.error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def read_partial(sock, length):
|
def read_partial(sock, length, buf=None):
|
||||||
return sock.recv(length)
|
if not buf:
|
||||||
|
buf = array.array("c", '\0' * length)
|
||||||
|
l = sock.recv_into(buf, length)
|
||||||
|
return buf[:l]
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
def write_chunk(sock, data):
|
def write_chunk(sock, data):
|
||||||
chunk = "".join(("%X\r\n" % len(data), data, "\r\n"))
|
chunk = "".join(("%X\r\n" % len(data), data, "\r\n"))
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
# This file is part of gunicorn released under the MIT license.
|
# This file is part of gunicorn released under the MIT license.
|
||||||
# See the NOTICE for more information.
|
# See the NOTICE for more information.
|
||||||
|
|
||||||
|
import array
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
@ -50,6 +51,13 @@ class FakeSocket(object):
|
|||||||
def recv(self, length=None):
|
def recv(self, length=None):
|
||||||
return self.tmp.read()
|
return self.tmp.read()
|
||||||
|
|
||||||
|
def recv_into(self, buf, length):
|
||||||
|
tmp_buffer = self.tmp.read(length)
|
||||||
|
v = len(tmp_buffer)
|
||||||
|
for i, c in enumerate(tmp_buffer):
|
||||||
|
buf[i] = c
|
||||||
|
return v
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
self.tmp.write(data)
|
self.tmp.write(data)
|
||||||
self.tmp.flush()
|
self.tmp.flush()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user