@@ -32,7 +32,13 @@ def json(self):
32
32
return ujson .loads (self .content )
33
33
34
34
35
+ def is_chunked_data (data ):
36
+ return getattr (data , "__iter__" , None ) and not getattr (data , "__len__" , None )
37
+
35
38
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
+
36
42
try :
37
43
proto , dummy , host , path = url .split ("/" , 3 )
38
44
except ValueError :
@@ -73,10 +79,20 @@ def request(method, url, data=None, json=None, headers={}, stream=None):
73
79
data = ujson .dumps (json )
74
80
s .write (b"Content-Type: application/json\r \n " )
75
81
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 ))
77
86
s .write (b"\r \n " )
78
87
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 )
80
96
81
97
l = s .readline ()
82
98
#print(l)
@@ -94,15 +110,25 @@ def request(method, url, data=None, json=None, headers={}, stream=None):
94
110
if b"chunked" in l :
95
111
raise ValueError ("Unsupported " + l )
96
112
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 )
98
117
except OSError :
99
118
s .close ()
100
119
raise
101
120
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
106
132
107
133
108
134
def head (url , ** kw ):
@@ -121,4 +147,4 @@ def patch(url, **kw):
121
147
return request ("PATCH" , url , ** kw )
122
148
123
149
def delete (url , ** kw ):
124
- return request ("DELETE" , url , ** kw )
150
+ return request ("DELETE" , url , ** kw )
0 commit comments