software.ellerton.net

Author: Andrew Ellerton
Last upated:July 2006

Python XML-RPC Proxy-compliant Transport

Download python file

#!/bin/env python
import xmlrpclib

class ProxyTransport(xmlrpclib.Transport):
    """Provides an XMl-RPC transport routing via a http proxy.
    
    This is done by using urllib2, which in turn uses the environment
    varable http_proxy and whatever else it is built to use (e.g. the
    windows registry).
    
    NOTE: the environment variable http_proxy should be set correctly.
    See checkProxySetting() below.
    
    Written from scratch but inspired by xmlrpc_urllib_transport.py
    file from http://starship.python.net/crew/jjkunce/ by jjk.
    
    A. Ellerton 2006-07-06
    """

    def request(self, host, handler, request_body, verbose):
        import urllib2
        self.verbose=verbose
        url='http://'+host+handler
        if self.verbose: "ProxyTransport URL: [%s]"%url

        request = urllib2.Request(url)
        request.add_data(request_body)
        # Note: 'Host' and 'Content-Length' are added automatically
        request.add_header("User-Agent", self.user_agent)
        request.add_header("Content-Type", "text/xml") # Important

        proxy_handler=urllib2.ProxyHandler()
        opener=urllib2.build_opener(proxy_handler)
        f=opener.open(request)
        return(self.parse_response(f))


def checkProxySetting():
    """If the variable 'http_proxy' is set, it will most likely be in one
    of these forms (not real host/ports):
    
          proxyhost:8080
          http://proxyhost:8080
    
    urlllib2 seems to require it to have 'http;//" at the start.
    This routine does that, and returns the transport for xmlrpc.
    """
    import os, re
    try:
        http_proxy=os.environ['http_proxy']
    except KeyError:
        return
    
    # ensure the proxy has the 'http://' at the start
    #
    match = re.match("(http://)?([-_\.A-Za-z]+):(\d+)", http_proxy)
    if not match: raise Exception("Proxy format not recognised: [%s]" % http_proxy)
    os.environ['http_proxy'] = "http://%s:%s" % (match.group(2), match.group(3))
    #print "Determined proxy: %s" % os.environ['http_proxy']
    return


def test():
    import sys, os
    
    def nextArg():
        try: return sys.argv.pop(1)
        except: return None

    checkProxySetting()
    
    url=nextArg() or "http://betty.userland.com"
    api=nextArg() or "examples.getStateName(32)" # "examples.getStateList([1,2])"
    try:
        server=xmlrpclib.Server(url, transport=ProxyTransport())
        print "Url: %s" % url
        
        try: print "Proxy: %s" % os.environ['http_proxy']
        except KeyError: print "Proxy: (Apparently none)"
        
        print "API: %s" % api
        r = eval("server.%s"%api)
        print "Result: ", r
        
    except xmlrpclib.ProtocolError, e:
        print "Connection error: %s" % e
    except xmlrpclib.Fault, e:
        print "Error: %s" % e

if __name__=='__main__':
    # run with no parameters for basic test case.
    test()