Python XML RPC over HTTP proxy

in

The XML-RPC over HTTP proxy given in Python documentation doesn't really work, so I've written a fixed XML-RPC transport for xmlrpclib that seems to work.

The reference version didn't work for a few reasons — seemingly there were internal API changes. Also it didn't send Content-Length that was required by some servers.

The syntax is for Python 3. To use with Python 2 you need to change xmlrpc.client to xmlrpclib and http.client to httplib.

import xmlrpc.client
import http.client
 
PROXY_HOST = 'proxy.example.com'
PROXY_PORT = 3128
 
class ProxiedTransport(xmlrpc.client.Transport):
    def __init__(self, proxy_host, proxy_port, use_datetime=False):
        self.proxy_host = proxy_host
        self.proxy_port = proxy_port
        self._connection = (None, None)
        self._use_datetime = use_datetime
    def send_request(self, host, handler, request_body, verbose=True):
        print(request_body)
        connection = self.make_connection(host)
        uri = 'http://{0}{1}'.format(host, handler)
        print(uri)
        connection.putrequest("POST", uri)
        connection.putheader("Content-Type", "text/xml")
        connection.putheader("Content-Length", len(request_body))
        connection.putheader("User-Agent", "xmlrpclib")
        connection.endheaders()
        connection.send(request_body)
        return connection
    def make_connection(self, host):
        if self._connection and host == self._connection[0]:
            return self._connection[1]
        self._connection = host, http.client.HTTPConnection(self.proxy_host, self.proxy_port)
        return self._connection[1]
 
if __name__ == "__main__":
    p = ProxiedTransport(PROXY_HOST, PROXY_PORT)
    server = xmlrpc.client.ServerProxy('http://www.cookcomputing.com/xmlrpcsamples/RPC2.ashx', transport=p)
    ret = server.system.listMethods()
    print(ret)
    ret = server.examples.getStateName(1)
    print(ret)

Note that the XML-RPC service used in this example is real and live (as of May 2012), courtesy of Cook Computing. It's great for testing, especially that it supports service enumeration (listMethods).