Skip to content

Commit 3167fd5

Browse files
committed
urequests: added support for chunked requests and redirection
1 parent eae01bd commit 3167fd5

File tree

1 file changed

+34
-8
lines changed

1 file changed

+34
-8
lines changed

urequests/urequests.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ def json(self):
3232
return ujson.loads(self.content)
3333

3434

35+
def is_chunked_data(data):
36+
return getattr(data, "__iter__", None) and not getattr(data, "__len__", None)
37+
3538
def request(method, url, data=None, json=None, headers={}, stream=None):
39+
chunked = data and is_chunked_data(data)
40+
redirect = None #redirection url, None means no redirection
41+
3642
try:
3743
proto, dummy, host, path = url.split("/", 3)
3844
except ValueError:
@@ -73,10 +79,20 @@ def request(method, url, data=None, json=None, headers={}, stream=None):
7379
data = ujson.dumps(json)
7480
s.write(b"Content-Type: application/json\r\n")
7581
if data:
76-
s.write(b"Content-Length: %d\r\n" % len(data))
82+
if chunked:
83+
s.write(b"Transfer-Encoding: chunked\r\n")
84+
else:
85+
s.write(b"Content-Length: %d\r\n" % len(data))
7786
s.write(b"\r\n")
7887
if data:
79-
s.write(data)
88+
if chunked:
89+
for chunk in data:
90+
s.write(b"%x\r\n" % len(chunk))
91+
s.write(chunk)
92+
s.write(b"\r\n")
93+
s.write("0\r\n\r\n")
94+
else:
95+
s.write(data)
8096

8197
l = s.readline()
8298
#print(l)
@@ -94,15 +110,25 @@ def request(method, url, data=None, json=None, headers={}, stream=None):
94110
if b"chunked" in l:
95111
raise ValueError("Unsupported " + l)
96112
elif l.startswith(b"Location:") and not 200 <= status <= 299:
97-
raise NotImplementedError("Redirects not yet supported")
113+
if status in [301, 302, 303, 307, 308]:
114+
redirect = l[10:-2].decode()
115+
else:
116+
raise NotImplementedError("Redirect %d not yet supported" % status)
98117
except OSError:
99118
s.close()
100119
raise
101120

102-
resp = Response(s)
103-
resp.status_code = status
104-
resp.reason = reason
105-
return resp
121+
if redirect:
122+
s.close()
123+
if status in [301, 302, 303]:
124+
return request("GET", redirect, None, None, headers, stream)
125+
else:
126+
return request(method, redirect, data, json, headers, stream)
127+
else:
128+
resp = Response(s)
129+
resp.status_code = status
130+
resp.reason = reason
131+
return resp
106132

107133

108134
def head(url, **kw):
@@ -121,4 +147,4 @@ def patch(url, **kw):
121147
return request("PATCH", url, **kw)
122148

123149
def delete(url, **kw):
124-
return request("DELETE", url, **kw)
150+
return request("DELETE", url, **kw)

0 commit comments

Comments
 (0)