[Zope-dev] ZSyncher and xml-rpc via firewalls

Dylan Jay djay@avaya.com
Mon, 2 Dec 2002 22:53:36 +1100


I was needing to use ZSyncher via a proxy server in our firewall. I wrote a
new transport to do this that you might want to incorporate into ZSyncher.
Nice product btw. Very helpful for my setup. Any chance of getting it to
synch bidirectionally?

import urllib

class AuthProxyTransport(xmlrpclib.Transport):
    '''Handles an HTTP transaction to an XML-RPC server via a http proxy and
using basic authentication djay@slarken.org.au '''

    def __init__(self, username=None, password=None):
        self.username = username
        self.password = password
        self.verbose = None
        self.has_ssl = 0
        self.proxies = urllib.getproxies()


    def request(self, host, handler, request_body, verbose=0):
        # issue XML-RPC request

        import httplib

        # Override to use proxies
        realhost = None
        if self.proxies.has_key("http"):
            realhost = host
            proxy = self.proxies["http"]
            urltype, proxyhost = urllib.splittype(proxy)
            host, selector = urllib.splithost(proxyhost)

        h = httplib.HTTP(host)

        if realhost:
            h.putrequest("POST", "http://" + realhost + handler)
        else:
            h.putrequest("POST", handler)

        # required by HTTP/1.1
        if realhost:
            h.putheader("Host", realhost)
        else:
            h.putheader("Host", host)

        # required by XML-RPC
        h.putheader("User-Agent", self.user_agent)
        h.putheader("Content-Type", "text/xml")
        h.putheader("Content-Length", str(len(request_body)))

        #Override to do authentication (should really use username and
password encoded in url like urllib)
        if self.username is not None and self.password is not None:
            h.putheader("AUTHORIZATION", "Basic %s" % string.replace(
                encodestring("%s:%s" % (self.username, self.password)),
                "\012", ""))

        h.endheaders()

        if request_body:
            h.send(request_body)

        errcode, errmsg, headers = h.getreply()

        if errcode != 200:
            raise xmlrpclib.ProtocolError(
                host + handler,
                errcode, errmsg,
                headers
                )

        return self.parse_response(h.getfile())