You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
63 lines
2.3 KiB
63 lines
2.3 KiB
# -*- coding: utf-8 -*-
|
|
|
|
import io
|
|
|
|
# Werkzeug version bundled into odoo doesn't handle this kind of Transfer-Encoding
|
|
# correctly. We copy the fix from https://github.com/pallets/werkzeug/pull/1198/files
|
|
class DechunkedInput(io.RawIOBase):
|
|
"""An input stream that handles Transfer-Encoding 'chunked'"""
|
|
|
|
def __init__(self, rfile):
|
|
self._rfile = rfile
|
|
self._done = False
|
|
self._len = 0
|
|
|
|
def readable(self):
|
|
return True
|
|
|
|
def read_chunk_len(self):
|
|
try:
|
|
line = self._rfile.readline().decode('latin1')
|
|
_len = int(line.strip(), 16)
|
|
except ValueError:
|
|
raise IOError('Invalid chunk header')
|
|
if _len < 0:
|
|
raise IOError('Negative chunk length not allowed')
|
|
return _len
|
|
|
|
def readinto(self, buf):
|
|
read = 0
|
|
while not self._done and read < len(buf):
|
|
if self._len == 0:
|
|
# This is the first chunk or we fully consumed the previous
|
|
# one. Read the next length of the next chunk
|
|
self._len = self.read_chunk_len()
|
|
|
|
if self._len == 0:
|
|
# Found the final chunk of size 0. The stream is now exhausted,
|
|
# but there is still a final newline that should be consumed
|
|
self._done = True
|
|
|
|
if self._len > 0:
|
|
# There is data (left) in this chunk, so append it to the
|
|
# buffer. If this operation fully consumes the chunk, this will
|
|
# reset self._len to 0.
|
|
n = min(len(buf), self._len)
|
|
buf[read:read + n] = self._rfile.read(n)
|
|
self._len -= n
|
|
read += n
|
|
|
|
if self._len == 0:
|
|
# Skip the terminating newline of a chunk that has been fully
|
|
# consumed. This also applies to the 0-sized final chunk
|
|
terminator = self._rfile.readline()
|
|
if terminator not in (b'\n', b'\r\n', b'\r'):
|
|
raise IOError('Missing chunk terminating newline')
|
|
|
|
return read
|
|
|
|
def http_input_stream(request):
|
|
if request.httprequest.headers.get('Transfer-Encoding') == 'chunked' \
|
|
and not request.httprequest.environ.get('wsgi.input_terminated'):
|
|
return DechunkedInput(request.httprequest.environ['wsgi.input'])
|
|
return request.httprequest.stream
|