33import os
44from six .moves import http_client
55from six .moves .urllib .parse import urlparse
6+ from ssl import SSLError
7+
68
79class Stream :
8- def __init__ (self , server , port = 80 , headers = {}, url = '/' ):
9- ''' Initialize a stream object and an HTTP Connection
10+ def __init__ (self , server , port = 80 , headers = {}, url = '/' , ssl_enabled = False ):
11+ ''' Initialize a stream object and an HTTP or HTTPS connection
1012 with chunked Transfer-Encoding to server:port with optional headers.
1113 '''
1214 self .maxtries = 5
@@ -17,6 +19,7 @@ def __init__(self, server, port=80, headers={}, url='/'):
1719 self ._port = port
1820 self ._headers = headers
1921 self ._url = url
22+ self ._ssl_enabled = ssl_enabled
2023 self ._connect ()
2124
2225 def write (self , data , reconnect_on = ('' , 200 , )):
@@ -73,17 +76,21 @@ def write(self, data, reconnect_on=('', 200, )):
7376 def _get_proxy_config (self ):
7477 """
7578 Determine if self._url should be passed through a proxy. If so, return
76- the appropriate proxy_server and proxy_port
79+ the appropriate proxy_server and proxy_port. Assumes https_proxy is used
80+ when ssl_enabled=True.
7781
7882 """
7983
8084 proxy_server = None
8185 proxy_port = None
86+ ssl_enabled = self ._ssl_enabled
8287
83- ## only doing HTTPConnection, so only use http_proxy
84- proxy = os .environ .get ("http_proxy" )
88+ if ssl_enabled :
89+ proxy = os .environ .get ("https_proxy" )
90+ else :
91+ proxy = os .environ .get ("http_proxy" )
8592 no_proxy = os .environ .get ("no_proxy" )
86- no_proxy_url = no_proxy and self ._url in no_proxy
93+ no_proxy_url = no_proxy and self ._server in no_proxy
8794
8895 if proxy and not no_proxy_url :
8996 p = urlparse (proxy )
@@ -93,19 +100,30 @@ def _get_proxy_config(self):
93100 return proxy_server , proxy_port
94101
95102 def _connect (self ):
96- ''' Initialize an HTTP connection with chunked Transfer-Encoding
103+ ''' Initialize an HTTP/HTTPS connection with chunked Transfer-Encoding
97104 to server:port with optional headers.
98105 '''
99106 server = self ._server
100107 port = self ._port
101108 headers = self ._headers
109+ ssl_enabled = self ._ssl_enabled
102110 proxy_server , proxy_port = self ._get_proxy_config ()
103111
104112 if (proxy_server and proxy_port ):
105- self ._conn = http_client .HTTPConnection (proxy_server , proxy_port )
113+ if ssl_enabled :
114+ self ._conn = http_client .HTTPSConnection (
115+ proxy_server , proxy_port
116+ )
117+ else :
118+ self ._conn = http_client .HTTPConnection (
119+ proxy_server , proxy_port
120+ )
106121 self ._conn .set_tunnel (server , port )
107122 else :
108- self ._conn = http_client .HTTPConnection (server , port )
123+ if ssl_enabled :
124+ self ._conn = http_client .HTTPSConnection (server , port )
125+ else :
126+ self ._conn = http_client .HTTPConnection (server , port )
109127
110128 self ._conn .putrequest ('POST' , self ._url )
111129 self ._conn .putheader ('Transfer-Encoding' , 'chunked' )
@@ -236,6 +254,16 @@ def _isconnected(self):
236254 # let's just assume that we're still connected and
237255 # hopefully recieve some data on the next try.
238256 return True
257+ elif isinstance (e , SSLError ):
258+ if e .errno == 2 :
259+ # errno 2 occurs when trying to read or write data, but more
260+ # data needs to be received on the underlying TCP transport
261+ # before the request can be fulfilled.
262+ #
263+ # Python 2.7.9+ and Python 3.3+ give this its own exception,
264+ # SSLWantReadError
265+ return True
266+ raise e
239267 else :
240268 # Unknown scenario
241269 raise e
0 commit comments