Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion ldclient/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def __init__(self,
offline=False,
user_keys_capacity=1000,
user_keys_flush_interval=300,
inline_users_in_events=False):
inline_users_in_events=False,
http_proxy=None):
"""
:param string sdk_key: The SDK key for your LaunchDarkly account.
:param string base_uri: The base URL for the LaunchDarkly server. Most users should use the default
Expand Down Expand Up @@ -95,6 +96,8 @@ def __init__(self,
:type event_processor_class: (ldclient.config.Config) -> EventProcessor
:param update_processor_class: A factory for an UpdateProcessor implementation taking the sdk key,
config, and FeatureStore implementation
:param http_proxy: Use a proxy when connecting to LaunchDarkly. This is the full URI of the
proxy; for example: http://my-proxy.com:1234.
"""
self.__sdk_key = sdk_key

Expand Down Expand Up @@ -126,6 +129,7 @@ def __init__(self,
self.__user_keys_capacity = user_keys_capacity
self.__user_keys_flush_interval = user_keys_flush_interval
self.__inline_users_in_events = inline_users_in_events
self.__http_proxy = http_proxy

@classmethod
def default(cls):
Expand Down Expand Up @@ -278,6 +282,10 @@ def user_keys_flush_interval(self):
def inline_users_in_events(self):
return self.__inline_users_in_events

@property
def http_proxy(self):
return self.__http_proxy

def _validate(self):
if self.offline is False and self.sdk_key is None or self.sdk_key is '':
log.warning("Missing or blank sdk_key.")
2 changes: 1 addition & 1 deletion ldclient/event_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class EventDispatcher(object):
def __init__(self, inbox, config, http_client):
self._inbox = inbox
self._config = config
self._http = create_http_pool_manager(num_pools=1, verify_ssl=config.verify_ssl) if http_client is None else http_client
self._http = create_http_pool_manager(num_pools=1, verify_ssl=config.verify_ssl, proxy_url=config.http_proxy) if http_client is None else http_client
self._close_http = (http_client is None) # so we know whether to close it later
self._disabled = False
self._outbox = EventBuffer(config.events_max_pending)
Expand Down
2 changes: 1 addition & 1 deletion ldclient/feature_requester.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
class FeatureRequesterImpl(FeatureRequester):
def __init__(self, config):
self._cache = dict()
self._http = create_http_pool_manager(num_pools=1, verify_ssl=config.verify_ssl)
self._http = create_http_pool_manager(num_pools=1, verify_ssl=config.verify_ssl, proxy_url=config.http_proxy)
self._config = config

def get_all_data(self):
Expand Down
5 changes: 3 additions & 2 deletions ldclient/sse_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

class SSEClient(object):
def __init__(self, url, last_id=None, retry=3000, connect_timeout=10, read_timeout=300, chunk_size=10000,
verify_ssl=False, http=None, **kwargs):
verify_ssl=False, http=None, http_proxy=None, **kwargs):
self.url = url
self.last_id = last_id
self.retry = retry
Expand All @@ -32,7 +32,8 @@ def __init__(self, url, last_id=None, retry=3000, connect_timeout=10, read_timeo
self._chunk_size = chunk_size

# Optional support for passing in an HTTP client
self.http = create_http_pool_manager(num_pools=1, verify_ssl=verify_ssl)
self.http = create_http_pool_manager(num_pools=1, verify_ssl=verify_ssl,
proxy_url=http_proxy)

# Any extra kwargs will be fed into the request call later.
self.requests_kwargs = kwargs
Expand Down
3 changes: 2 additions & 1 deletion ldclient/streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def _connect(self):
headers=_stream_headers(self._config.sdk_key),
connect_timeout=self._config.connect_timeout,
read_timeout=stream_read_timeout,
verify_ssl=self._config.verify_ssl)
verify_ssl=self._config.verify_ssl,
http_proxy=self._config.http_proxy)

def stop(self):
log.info("Stopping StreamingUpdateProcessor")
Expand Down
37 changes: 30 additions & 7 deletions ldclient/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,37 @@ def status(self):
return self._status


def create_http_pool_manager(num_pools=1, verify_ssl=False):
def create_http_pool_manager(num_pools=1, verify_ssl=False, proxy_url=None):
"""
Create an http pool

:param num_pools: The number of connections in the pool.
:param verify_ssl: If true, force the connections to verify valid SSL.
:param proxy_url: If set, proxy connections through the proxy at this URL.

:return: A connection pool that implements urllib3.PoolManager
"""
if not verify_ssl:
return urllib3.PoolManager(num_pools=num_pools)
return urllib3.PoolManager(
num_pools=num_pools,
cert_reqs='CERT_REQUIRED',
ca_certs=certifi.where()
)
# Case: create a manager that does not need to respect SSL
if proxy_url is not None:
return urllib3.ProxyManager(num_pools=num_pools, proxy_url=proxy_url)
else:
return urllib3.PoolManager(num_pools=num_pools)
else:
# Case: force the connection to respect SSL
if proxy_url is not None:
return urllib3.ProxyManager(
num_pools=num_pools,
cert_reqs='CERT_REQUIRED',
ca_certs=certifi.where(),
proxy_url=proxy_url
)
else:
return urllib3.PoolManager(
num_pools=num_pools,
cert_reqs='CERT_REQUIRED',
ca_certs=certifi.where()
)


def throw_if_unsuccessful_response(resp):
Expand Down