diff -r 56f71f02206e -r 9b2d2fd6c3a7 Doc/library/xmlrpc.client.rst --- a/Doc/library/xmlrpc.client.rst Tue Dec 16 18:17:18 2014 -0800 +++ b/Doc/library/xmlrpc.client.rst Tue Dec 16 22:43:38 2014 -0800 @@ -32,6 +32,17 @@ For https URIs, :mod:`xmlrpc.client` now performs all the necessary certificate and hostname checks by default +.. versionchanged:: 3.5 + + The *connection_factory* parameter was added to + :class:`xmlrpc.client.Transport` to allow for customization of the + underlying :class:`http.client.HTTPConnection` and + :class:`http.client.HTTPSConnection` objects. This allows for + modifications as simple as changing the connection timeout value and as + complex as swapping the standard library :class:`http.client.HTTPConnection` + client out for an entirely customized class (note that the + :class:`http.client.HTTPConnection` API must still be adhered to. + .. class:: ServerProxy(uri, transport=None, encoding=None, verbose=False, \ allow_none=False, use_datetime=False, \ use_builtin_types=False, *, context=None) @@ -567,6 +578,18 @@ server = xmlrpc.client.Server('http://time.xmlrpc.com/RPC2', transport=p) print(server.currentTime.getCurrentTime()) +To modify the underlying :class:`http.client.HTTPConnection` of the +:class:`xmlrpc.client.Transport`, you need to provide a connection instance +through the *connection_factory* callable. In this example, a connection object +is provided that changes the connection timeout to 2 seconds:: + + import xmlrpc.client, http.client + + transport = Transport(connection_factory=lambda host: + http.client.HTTPConnection(host, timeout=2) + + proxy = ServerProxy("http://betty.userland.com", transport=transport) + Example of Client and Server Usage ---------------------------------- diff -r 56f71f02206e -r 9b2d2fd6c3a7 Lib/xmlrpc/client.py --- a/Lib/xmlrpc/client.py Tue Dec 16 18:17:18 2014 -0800 +++ b/Lib/xmlrpc/client.py Tue Dec 16 22:43:38 2014 -0800 @@ -1118,11 +1118,13 @@ # that they can decode such a request encode_threshold = None #None = don't encode - def __init__(self, use_datetime=False, use_builtin_types=False): + def __init__(self, use_datetime=False, use_builtin_types=False, + connection_factory=lambda host: http.client.HTTPConnection(host)): self._use_datetime = use_datetime self._use_builtin_types = use_builtin_types self._connection = (None, None) self._extra_headers = [] + self._connection_factory = connection_factory ## # Send a complete request, and parse the response. @@ -1228,7 +1230,7 @@ return self._connection[1] # create a HTTP connection object from a host descriptor chost, self._extra_headers, x509 = self.get_host_info(host) - self._connection = host, http.client.HTTPConnection(chost) + self._connection = host, self._connection_factory(chost) return self._connection[1] ## @@ -1330,12 +1332,18 @@ ## # Standard transport class for XML-RPC over HTTPS. +def _safe_connection_factory(host, port, context, **kwargs): + return http.client.HTTPSConnection(host, port, context=context, **kwargs) + class SafeTransport(Transport): """Handles an HTTPS transaction to an XML-RPC server.""" def __init__(self, use_datetime=False, use_builtin_types=False, *, - context=None): - super().__init__(use_datetime=use_datetime, use_builtin_types=use_builtin_types) + context=None, connection_factory=_safe_connection_factory): + super().__init__( + use_datetime=use_datetime, + use_builtin_types=use_builtin_types, + connection_factory=connection_factory) self.context = context # FIXME: mostly untested @@ -1350,7 +1358,7 @@ # create a HTTPS connection object from a host descriptor # host may be a string, or a (host, x509-dict) tuple chost, self._extra_headers, x509 = self.get_host_info(host) - self._connection = host, http.client.HTTPSConnection(chost, + self._connection = host, self._connection_factory(chost, None, context=self.context, **(x509 or {})) return self._connection[1]