@@ -43,8 +43,8 @@ class HTTP11Connection(object):
4343 :param host: The host to connect to. This may be an IP address or a
4444 hostname, and optionally may include a port: for example,
4545 ``'twitter.com'``, ``'twitter.com:443'`` or ``'127.0.0.1'``.
46- :param port: (optional) The port to connect to. If not provided and one also
47- isn't provided in the ``host`` parameter, defaults to 80.
46+ :param port: (optional) The port to connect to. If not provided and one
47+ also isn't provided in the ``host`` parameter, defaults to 80.
4848 :param secure: (optional) Whether the request should use TLS. Defaults to
4949 ``False`` for most requests, but to ``True`` for any request issued to
5050 port 443.
@@ -82,7 +82,9 @@ def __init__(self, host, port=None, secure=None, ssl_context=None,
8282 # Setup proxy details if applicable.
8383 if proxy_host :
8484 if proxy_port is None :
85- self .proxy_host , self .proxy_port = to_host_port_tuple (proxy_host , default_port = 8080 )
85+ self .proxy_host , self .proxy_port = to_host_port_tuple (
86+ proxy_host , default_port = 8080
87+ )
8688 else :
8789 self .proxy_host , self .proxy_port = proxy_host , proxy_port
8890 else :
@@ -118,7 +120,7 @@ def connect(self):
118120 proto = None
119121
120122 if self .secure :
121- assert not self .proxy_host , "Using a proxy with HTTPS not yet supported."
123+ assert not self .proxy_host , "Proxy with HTTPS not supported."
122124 sock , proto = wrap_socket (sock , host , self .ssl_context )
123125
124126 log .debug ("Selected protocol: %s" , proto )
@@ -142,8 +144,8 @@ def request(self, method, url, body=None, headers=None):
142144
143145 :param method: The request method, e.g. ``'GET'``.
144146 :param url: The URL to contact, e.g. ``'/path/segment'``.
145- :param body: (optional) The request body to send. Must be a bytestring, an iterable of bytestring
146- or a file-like object.
147+ :param body: (optional) The request body to send. Must be a bytestring,
148+ an iterable of bytestring, or a file-like object.
147149 :param headers: (optional) The headers to send on the request.
148150 :returns: Nothing.
149151 """
@@ -159,7 +161,9 @@ def request(self, method, url, body=None, headers=None):
159161 elif isinstance (headers , Iterable ):
160162 headers = HTTPHeaderMap (headers )
161163 else :
162- raise ValueError ('Header argument must be a dictionary or an iterable' )
164+ raise ValueError (
165+ 'Header argument must be a dictionary or an iterable'
166+ )
163167
164168 if self ._sock is None :
165169 self .connect ()
@@ -205,8 +209,8 @@ def get_response(self):
205209 self ._sock .advance_buffer (response .consumed )
206210
207211 if (response .status == 101 and
208- b'upgrade' in headers ['connection' ] and
209- H2C_PROTOCOL .encode ('utf-8' ) in headers ['upgrade' ]):
212+ b'upgrade' in headers ['connection' ] and
213+ H2C_PROTOCOL .encode ('utf-8' ) in headers ['upgrade' ]):
210214 raise HTTPUpgrade (H2C_PROTOCOL , self ._sock )
211215
212216 return HTTP11Response (
@@ -265,10 +269,13 @@ def _add_upgrade_headers(self, headers):
265269 headers [b'connection' ] = b'Upgrade, HTTP2-Settings'
266270 headers [b'upgrade' ] = H2C_PROTOCOL
267271
268- # Encode SETTINGS frame payload in Base64 and put into the HTTP-2 Settings header.
272+ # Encode SETTINGS frame payload in Base64 and put into the HTTP-2
273+ # Settings header.
269274 http2_settings = SettingsFrame (0 )
270275 http2_settings .settings [SettingsFrame .INITIAL_WINDOW_SIZE ] = 65535
271- encoded_settings = base64 .urlsafe_b64encode (http2_settings .serialize_body ())
276+ encoded_settings = base64 .urlsafe_b64encode (
277+ http2_settings .serialize_body ()
278+ )
272279 headers [b'HTTP2-Settings' ] = encoded_settings .rstrip (b'=' )
273280
274281 def _send_body (self , body , body_type ):
@@ -279,17 +286,7 @@ def _send_body(self, body, body_type):
279286 if body_type == BODY_FLAT :
280287 # Special case for files and other 'readable' objects.
281288 if hasattr (body , 'read' ):
282- while True :
283- block = body .read (16 * 1024 )
284- if not block :
285- break
286-
287- try :
288- self ._sock .send (block )
289- except TypeError :
290- raise ValueError ("File-like bodies must return bytestrings. Got: {}" .format (type (block )))
291-
292- return
289+ return self ._send_file_like_obj (body )
293290
294291 # Case for bytestrings.
295292 elif isinstance (body , bytes ):
@@ -303,14 +300,26 @@ def _send_body(self, body, body_type):
303300 try :
304301 self ._sock .send (item )
305302 except TypeError :
306- raise ValueError ("Elements in iterable body must be bytestrings. "
307- "Illegal element: {}" .format (item ))
303+ raise ValueError (
304+ "Elements in iterable body must be bytestrings. "
305+ "Illegal element: {}" .format (item )
306+ )
308307 return
309308
310309 else :
311- raise ValueError ('Request body must be a bytestring, a file-like object returning bytestrings '
312- 'or an iterable of bytestrings. Got: {}' .format (type (body )))
310+ raise ValueError (
311+ 'Request body must be a bytestring, a file-like object '
312+ 'returning bytestrings or an iterable of bytestrings. '
313+ 'Got: {}' .format (type (body ))
314+ )
315+
316+ # Chunked!
317+ return self ._send_chunked (body )
313318
319+ def _send_chunked (self , body ):
320+ """
321+ Handles the HTTP/1.1 logic for sending a chunk-encoded body.
322+ """
314323 # Chunked! For chunked bodies we don't special-case, we just iterate
315324 # over what we have and send stuff out.
316325 for chunk in body :
@@ -324,11 +333,32 @@ def _send_body(self, body, body_type):
324333 self ._sock .send (chunk )
325334 self ._sock .send (b'\r \n ' )
326335 except TypeError :
327- raise ValueError ("Iterable bodies must always iterate in bytestrings" )
336+ raise ValueError (
337+ "Iterable bodies must always iterate in bytestrings"
338+ )
328339
329340 self ._sock .send (b'0\r \n \r \n ' )
330341 return
331342
343+ def _send_file_like_obj (self , fobj ):
344+ """
345+ Handles streaming a file-like object to the network.
346+ """
347+ while True :
348+ block = fobj .read (16 * 1024 )
349+ if not block :
350+ break
351+
352+ try :
353+ self ._sock .send (block )
354+ except TypeError :
355+ raise ValueError (
356+ "File-like bodies must return bytestrings. Got: "
357+ "{}" .format (type (block ))
358+ )
359+
360+ return
361+
332362 def close (self ):
333363 """
334364 Closes the connection. This closes the socket and then abandons the
0 commit comments