Source code for ahoyhoy.servicediscovery.servicediscovery

import logging
from ..http import SessionProxy


logger = logging.getLogger(__name__)


[docs]class ServiceDiscoveryAdapter(object): """ Adapter intended to be used as a mixin along with a :class:`~ahoyhoy.http.proxy.SessionProxy` in order to calculate a `protocol://host:port` string to be added to the `path` for a complete url. """ def __init__(self, host, *args, **kwargs): self._host = host self._protocol = self.calculate_protocol(self.port) self._pre = kwargs.pop('pre_callback', None) self._post = kwargs.pop('post_callback', None) self._exc = kwargs.pop('exception_callback', None) # pass anything left on to superclasses super(ServiceDiscoveryAdapter, self).__init__(*args, **kwargs) @property def host(self): """Returns the endpoint's host""" return self._host @property def address(self): """Returns the endpoint's address""" return self.host.address @property def port(self): """Returns the endpoint's port""" return self.host.port @property def protocol(self): return self._protocol @property def url(self): """Returns the 'protocol://host:port' url""" url = '{}://{}'.format(self.protocol, self.address) if self.port: url += ':{}'.format(self.port) return url def __eq__(self, other): """Only want to check protocol, host, port, and url contains all.""" return self.host == other.host def __ne__(self, other): return not self == other def __str__(self): return "{}:{}".format(self._host, self._port)
[docs] def calculate_protocol(self, port): """ Use port for calculating the protocol. :param port: """ if port is '443': return 'https' else: # default to http return 'http'
[docs] def pre_callback(self, urlpath): """ Calculate and return the url to be passed to the Requests Session, using self.url (calculated from self.[host|port|protocol]). """ if self._pre is None: request_url = self.url + urlpath logger.info("Using resolved url: %s", request_url) return request_url return self._pre(self, urlpath)
def post_callback(self, result): # needs to be over-ridden to pass the correct "self" if self._post is None: return result return self._post(self, result) def exception_callback(self, exc): # again, needs to be overridden to pass the correct "self" if self._exc is None: raise exc return self._exc(self, exc)
[docs]class ServiceDiscoveryHttpClient(ServiceDiscoveryAdapter, SessionProxy): """ An object that transparently allows Service Discovery while preserving the same API as a Requests Session object, so typical Requests methods take server-relative paths rather than full URLs. For instance, here's how you can make a Http GET request using Requests's standard `get` method. >>> from ahoyhoy.servicediscovery import ServiceDiscoveryHttpClient >>> from ahoyhoy.utils import Host >>> host = Host('google.com', '80') >>> sdhc = ServiceDiscoveryHttpClient(host) >>> sdhc.get('/') <Response [200]> Note the fact that we're passing `get` a path, _not_ a URL. Why? When using a form of Service Discovery, host/port (and sometimes protocol) portions of the URL are resolved at runtime. This class adapts the a Requests Session in order to support this runtime service resolution. """ def __init__(self, *args, **kwargs): super(ServiceDiscoveryHttpClient, self).__init__(*args, **kwargs)