33
38
raise IllegalKeywordArgument()
35
40
self.ssl_ctx = ssl['ssl_context']
36
assert isinstance(self.ssl_ctx, SSL.Context)
41
assert isinstance(self.ssl_ctx, SSL.Context), self.ssl_ctx
38
43
self.ssl_ctx = SSL.Context('sslv23')
39
44
HTTPConnection.__init__(self, host, port, strict)
42
47
self.sock = SSL.Connection(self.ssl_ctx)
49
self.sock.set_session(self.session)
43
50
self.sock.connect((self.host, self.port))
72
85
self.ssl_ctx = SSL.Context('sslv23')
73
86
assert isinstance(self._conn, HTTPSConnection)
74
87
self._conn.ssl_ctx = self.ssl_ctx
90
class ProxyHTTPSConnection(HTTPSConnection):
93
An HTTPS Connection that uses a proxy and the CONNECT request.
95
When the connection is initiated, CONNECT is first sent to the proxy (along
96
with authorization headers, if supplied). If successful, an SSL connection
97
will be established over the socket through the proxy and to the target
100
Finally, the actual request is sent over the SSL connection tunneling
104
_ports = {'http' : 80, 'https' : 443}
105
_AUTH_HEADER = "Proxy-Authorization"
107
def __init__(self, host, port=None, strict=None, username=None,
108
password=None, **ssl):
110
Create the ProxyHTTPSConnection object.
112
host and port are the hostname and port number of the proxy server.
114
HTTPSConnection.__init__(self, host, port, strict, **ssl)
116
self._username = username
117
self._password = password
118
self._proxy_auth = None
120
def putrequest(self, method, url, skip_host=0, skip_accept_encoding=0):
121
#putrequest is called before connect, so can interpret url and get
122
#real host/port to be used to make CONNECT request to proxy
123
proto, rest = urllib.splittype(url)
125
raise ValueError, "unknown URL type: %s" % url
127
host, rest = urllib.splithost(rest)
129
host, port = urllib.splitport(host)
130
#if port is not defined try to get from proto
133
port = self._ports[proto]
135
raise ValueError, "unknown protocol for: %s" % url
136
self._real_host = host
137
self._real_port = port
138
HTTPSConnection.putrequest(self, method, url, skip_host, skip_accept_encoding)
140
def putheader(self, header, value):
141
# Store the auth header if passed in.
142
if header.lower() == self._AUTH_HEADER.lower():
143
self._proxy_auth = value
145
HTTPSConnection.putheader(self, header, value)
147
def endheaders(self):
148
# We've recieved all of hte headers. Use the supplied username
149
# and password for authorization, possibly overriding the authstring
150
# supplied in the headers.
151
if not self._proxy_auth:
152
self._proxy_auth = self._encode_auth()
154
HTTPSConnection.endheaders(self)
157
HTTPConnection.connect(self)
159
#send proxy CONNECT request
160
self.sock.sendall(self._get_connect_msg())
161
response = HTTPResponse(self.sock)
164
code = response.status
166
#proxy returned and error, abort connection, and raise exception
168
raise socket.error, "Proxy connection failed: %d" % code
172
def _get_connect_msg(self):
173
""" Return an HTTP CONNECT request to send to the proxy. """
174
msg = "CONNECT %s:%d HTTP/1.1\r\n" % (self._real_host, self._real_port)
176
msg = msg + "%s: %s\r\n" % (self._AUTH_HEADER, self._proxy_auth)
180
def _start_ssl(self):
181
""" Make this connection's socket SSL-aware. """
182
self.sock = SSL.Connection(self.ssl_ctx, self.sock)
183
self.sock.setup_ssl()
184
self.sock.set_connect_state()
185
self.sock.connect_ssl()
187
def _encode_auth(self):
188
""" Encode the username and password for use in the auth header. """
189
if not (self._username and self._password):
191
# Authenticated proxy
192
userpass = "%s:%s" % (self._username, self._password)
193
enc_userpass = base64.encodestring(userpass).replace("\n", "")
194
return "Basic %s" % enc_userpass