uaiohttpclient: Implement support for chunked transfer encoding.

Chunked T-E is mandatory for HTTP/1.1, and thus prerequisite for supporting
it.
pull/226/merge
Paul Sokolovsky 2014-11-28 23:20:19 +02:00
rodzic 8c1e077fc0
commit 5e1af0f277
1 zmienionych plików z 38 dodań i 2 usunięć

Wyświetl plik

@ -13,6 +13,35 @@ class ClientResponse:
return "<ClientResponse %d %s>" % (self.status, self.headers) return "<ClientResponse %d %s>" % (self.status, self.headers)
class ChunkedClientResponse(ClientResponse):
def __init__(self, reader):
self.content = reader
self.chunk_size = 0
def read(self, sz=4*1024*1024):
if self.chunk_size == 0:
l = yield from self.content.readline()
#print("chunk line:", l)
l = l.split(b";", 1)[0]
self.chunk_size = int(l, 16)
#print("chunk size:", self.chunk_size)
if self.chunk_size == 0:
# End of message
sep = yield from self.content.read(2)
assert sep == b"\r\n"
return b''
data = yield from self.content.read(min(sz, self.chunk_size))
self.chunk_size -= len(data)
if self.chunk_size == 0:
sep = yield from self.content.read(2)
assert sep == b"\r\n"
return data
def __repr__(self):
return "<ChunkedClientResponse %d %s>" % (self.status, self.headers)
def request_raw(method, url): def request_raw(method, url):
try: try:
proto, dummy, host, path = url.split("/", 3) proto, dummy, host, path = url.split("/", 3)
@ -31,16 +60,23 @@ def request_raw(method, url):
def request(method, url): def request(method, url):
reader = yield from request_raw(method, url) reader = yield from request_raw(method, url)
resp = ClientResponse(reader)
headers = [] headers = []
sline = yield from reader.readline() sline = yield from reader.readline()
protover, st, msg = sline.split(None, 2) protover, st, msg = sline.split(None, 2)
resp.status = int(st) chunked = False
while True: while True:
line = yield from reader.readline() line = yield from reader.readline()
if not line or line == b"\r\n": if not line or line == b"\r\n":
break break
headers.append(line) headers.append(line)
if line.startswith(b"Transfer-Encoding:"):
if b"chunked" in line:
chunked = True
if chunked:
resp = ChunkedClientResponse(reader)
else:
resp = ClientResponse(reader)
resp.status = int(st)
resp.headers = headers resp.headers = headers
return resp return resp