Setup proxy using a requests session instead of instantiating sockets
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/41919008 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/41919008 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/41919008 Branch: refs/heads/requests Commit: 41919008fcb86c2d914c2927ca691f6d980f15f2 Parents: 96f69cf Author: anthony-shaw <[email protected]> Authored: Sun Mar 27 11:50:07 2016 +1100 Committer: anthony-shaw <[email protected]> Committed: Sun Mar 27 11:50:07 2016 +1100 ---------------------------------------------------------------------- libcloud/httplib_ssl.py | 92 ++++++++------------------------ libcloud/test/secrets.py | 91 +++++++++++++++++++++++++++++++ libcloud/test/test_connection.py | 2 +- libcloud/utils/loggingconnection.py | 2 +- 4 files changed, 115 insertions(+), 72 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/httplib_ssl.py ---------------------------------------------------------------------- diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py index 2cf00fb..6e89a14 100644 --- a/libcloud/httplib_ssl.py +++ b/libcloud/httplib_ssl.py @@ -64,6 +64,8 @@ class LibcloudBaseConnection(object): Note: This class should not be instantiated directly. """ + session = None + proxy_scheme = None proxy_host = None proxy_port = None @@ -73,6 +75,9 @@ class LibcloudBaseConnection(object): http_proxy_used = False + def __init__(self): + self.session = requests.Session() + def set_http_proxy(self, proxy_url): """ Set a HTTP proxy which will be used with this connection. @@ -97,7 +102,9 @@ class LibcloudBaseConnection(object): self.proxy_password = password self.http_proxy_used = True - self._setup_http_proxy() + self.session.proxies = { + self.proxy_scheme: proxy_url + } def _parse_proxy_url(self, proxy_url): """ @@ -137,61 +144,6 @@ class LibcloudBaseConnection(object): return (proxy_scheme, proxy_host, proxy_port, proxy_username, proxy_password) - def _setup_http_proxy(self): - """ - Set up HTTP proxy. - - :param proxy_url: Proxy URL (e.g. http://<host>:3128) - :type proxy_url: ``str`` - """ - headers = {} - - if self.proxy_username and self.proxy_password: - # Include authentication header - user_pass = '%s:%s' % (self.proxy_username, self.proxy_password) - encoded = base64.encodestring(b(urlunquote(user_pass))).strip() - auth_header = 'Basic %s' % (encoded.decode('utf-8')) - headers['Proxy-Authorization'] = auth_header - - if hasattr(self, 'set_tunnel'): - # Python 2.7 and higher - # pylint: disable=no-member - self.set_tunnel(host=self.host, port=self.port, headers=headers) - elif hasattr(self, '_set_tunnel'): - # Python 2.6 - # pylint: disable=no-member - self._set_tunnel(host=self.host, port=self.port, headers=headers) - else: - raise ValueError('Unsupported Python version') - - self._set_hostport(host=self.proxy_host, port=self.proxy_port) - - def _activate_http_proxy(self, sock): - self.sock = sock - self._tunnel() # pylint: disable=no-member - - def _set_hostport(self, host, port): - """ - Backported from Python stdlib so Proxy support also works with - Python 3.4. - """ - if port is None: - i = host.rfind(':') - j = host.rfind(']') # ipv6 addresses have [...] - if i > j: - try: - port = int(host[i + 1:]) - except ValueError: - msg = "nonnumeric port: '%s'" % (host[i + 1:]) - raise httplib.InvalidURL(msg) - host = host[:i] - else: - port = self.default_port # pylint: disable=no-member - if host and host[0] == '[' and host[-1] == ']': - host = host[1:-1] - self.host = host - self.port = port - class LibcloudHTTPConnection(LibcloudBaseConnection): def __init__(self, *args, **kwargs): @@ -199,23 +151,23 @@ class LibcloudHTTPConnection(LibcloudBaseConnection): proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None) proxy_url = kwargs.pop('proxy_url', proxy_url_env) - super(LibcloudHTTPConnection, self).__init__(*args, **kwargs) + super(LibcloudHTTPConnection, self).__init__() if proxy_url: self.set_http_proxy(proxy_url=proxy_url) - def connect(): - pass + def connect(): + pass - def request(method, url, body=None, headers=None): - method = method.lower() - if method == 'get': - response = requests.get(url, headers=headers) - elif method == 'post': - response = requests.post(url, data=body, headers=headers) - elif method == 'head': - response = requests.head(url, headers=headers) - return response + def request(self, method, url, body=None, headers=None): + method = method.lower() + if method == 'get': + response = self.session.get(url, headers=headers) + elif method == 'post': + response = self.session.post(url, data=body, headers=headers) + elif method == 'head': + response = self.session.head(url, headers=headers) + return response class LibcloudHTTPSConnection(LibcloudBaseConnection): @@ -237,7 +189,7 @@ class LibcloudHTTPSConnection(LibcloudBaseConnection): proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None) proxy_url = kwargs.pop('proxy_url', proxy_url_env) - super(LibcloudHTTPSConnection, self).__init__(*args, **kwargs) + super(LibcloudHTTPSConnection, self).__init__() if proxy_url: self.set_http_proxy(proxy_url=proxy_url) @@ -281,7 +233,7 @@ class LibcloudHTTPSConnection(LibcloudBaseConnection): def connect(self): pass - def request(method, url, body=None, headers=None): + def request(self, method, url, body=None, headers=None): method = method.lower() if method == 'get': response = requests.get(url, headers=headers) http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/test/secrets.py ---------------------------------------------------------------------- diff --git a/libcloud/test/secrets.py b/libcloud/test/secrets.py index 5b228bc..480ac3f 100644 --- a/libcloud/test/secrets.py +++ b/libcloud/test/secrets.py @@ -1 +1,92 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Make a copy of this file named 'secrets.py' and add your credentials there. +# Note you can run unit tests without setting your credentials. + +BLUEBOX_PARAMS = ('customer_id', 'api_key') +BRIGHTBOX_PARAMS = ('client_id', 'client_secret') +EC2_PARAMS = ('access_id', 'secret') +ECP_PARAMS = ('user_name', 'password') +GANDI_PARAMS = ('user',) +GCE_PARAMS = ('[email protected]', 'key') # Service Account Authentication +# GCE_PARAMS = ('client_id', 'client_secret') # Installed App Authentication +GCE_KEYWORD_PARAMS = {'project': 'project_name'} +HOSTINGCOM_PARAMS = ('user', 'secret') +IBM_PARAMS = ('user', 'secret') +ONAPP_PARAMS = ('key',) +# OPENSTACK_PARAMS = ('user_name', 'api_key', secure_bool, 'host', port_int) +OPENSTACK_PARAMS = ('user_name', 'api_key', False, 'host', 8774) +OPENNEBULA_PARAMS = ('user', 'key') +DIMENSIONDATA_PARAMS = ('user', 'password') +OPSOURCE_PARAMS = ('user', 'password') +RUNABOVE_PARAMS = ('application_key', 'application_secret', 'consumer_key') +RACKSPACE_PARAMS = ('user', 'key') +RACKSPACE_NOVA_PARAMS = ('user_name', 'api_key', False, 'host', 8774) +SLICEHOST_PARAMS = ('key',) +SOFTLAYER_PARAMS = ('user', 'api_key') +VCLOUD_PARAMS = ('user', 'secret') +VOXEL_PARAMS = ('key', 'secret') +VPSNET_PARAMS = ('user', 'key') +JOYENT_PARAMS = ('user', 'key') +VCL_PARAMS = ('user', 'pass', True, 'foo.bar.com') +GRIDSPOT_PARAMS = ('key',) +HOSTVIRTUAL_PARAMS = ('key',) +DIGITALOCEAN_v1_PARAMS = ('user', 'key') +DIGITALOCEAN_v2_PARAMS = ('token',) +CLOUDFRAMES_PARAMS = ('key', 'secret', False, 'host', 8888) +PROFIT_BRICKS_PARAMS = ('user', 'key') +VULTR_PARAMS = ('key') +PACKET_PARAMS = ('api_key') +ECS_PARAMS = ('access_key', 'access_secret') + +# Storage +STORAGE_S3_PARAMS = ('key', 'secret') +STORAGE_OSS_PARAMS = ('key', 'secret') +# Google key = 20 char alphanumeric string starting with GOOG +STORAGE_GOOGLE_STORAGE_PARAMS = ('GOOG0123456789ABCXYZ', 'secret') + +# Azure key is b64 encoded and must be decoded before signing requests +STORAGE_AZURE_BLOBS_PARAMS = ('account', 'cGFzc3dvcmQ=') + +# Loadbalancer +LB_BRIGHTBOX_PARAMS = ('user', 'key') +LB_ELB_PARAMS = ('access_id', 'secret', 'region') +LB_SLB_PARAMS = ('access_id', 'secret', 'region') + +# DNS +DNS_PARAMS_LINODE = ('user', 'key') +DNS_PARAMS_ZERIGO = ('email', 'api token') +DNS_PARAMS_RACKSPACE = ('user', 'key') +DNS_PARAMS_HOSTVIRTUAL = ('key',) +DNS_PARAMS_ROUTE53 = ('access_id', 'secret') +DNS_GANDI = ('user', ) +DNS_PARAMS_GOOGLE = ('email_address', 'key') +DNS_KEYWORD_PARAMS_GOOGLE = {'project': 'project_name'} +DNS_PARAMS_WORLDWIDEDNS = ('user', 'key') +DNS_PARAMS_DNSIMPLE = ('user', 'key') +DNS_PARAMS_POINTDNS = ('user', 'key') +DNS_PARAMS_LIQUIDWEB = ('user', 'key') +DNS_PARAMS_ZONOMI = ('key') +DNS_PARAMS_DURABLEDNS = ('api_user', 'api_key') +DNS_PARAMS_GODADDY = ('customer-id', 'api_user', 'api_key') +DNS_PARAMS_CLOUDFLARE = ('[email protected]', 'key') +DNS_PARAMS_AURORADNS = ('apikey', 'secretkey') DNS_PARAMS_NSONE = ('key', ) + +# Container +CONTAINER_PARAMS_DOCKER = ('user', 'password') +CONTAINER_PARAMS_ECS = ('user', 'password', 'region') +CONTAINER_PARAMS_KUBERNETES = ('user', 'password') http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/test/test_connection.py ---------------------------------------------------------------------- diff --git a/libcloud/test/test_connection.py b/libcloud/test/test_connection.py index 783ed6a..a588ca6 100644 --- a/libcloud/test/test_connection.py +++ b/libcloud/test/test_connection.py @@ -23,7 +23,7 @@ from mock import Mock, call, patch from libcloud.test import unittest from libcloud.common.base import Connection -from libcloud.common.utils.loggingconnection import LoggingConnection +from libcloud.utils.loggingconnection import LoggingConnection from libcloud.httplib_ssl import LibcloudBaseConnection from libcloud.httplib_ssl import LibcloudHTTPConnection from libcloud.utils.misc import retry http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/utils/loggingconnection.py ---------------------------------------------------------------------- diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py index bffd8f9..2b6550d 100644 --- a/libcloud/utils/loggingconnection.py +++ b/libcloud/utils/loggingconnection.py @@ -23,11 +23,11 @@ import xml.dom.minidom import sys import os -import httplib from libcloud.common.base import (LibcloudHTTPConnection, LibcloudHTTPSConnection, HTTPResponse) +from libcloud.utils.py3 import httplib from libcloud.utils.py3 import PY3 from libcloud.utils.py3 import StringIO from libcloud.utils.py3 import u
