[Twisted-web] twisted.web.xmlrpc.Proxy plus user and password

Timothy Stebbing tjs at nunatak.com.au
Tue Aug 9 20:31:28 MDT 2005


Dave Kuhlman wrote:

>I'm trying to write an XML-RPC client that will send requests to
>an XML-RPC server which requires a user ID and password.  In
>xmlrpclib, the URL format for this is:
>
>    http://userid:password@somehost:aport/...
>
>But, twisted.web.xmlrpc.Proxy does not seem to support this.
>
>So, is there a way to write a Twisted XML-RPC client that passes
>in user name and password?  And, if so, how do I do that?
>
>I've searched the documentation and done some other searches, but
>can't find this.
>
>Thanks for any help.
>
>Dave
>
>
>  
>
We wrote this at work a while back for communicating with zope xmlrpc, 
hope it helps:

"""
A slight extension to twisted.web.xmlrpc for basic auth support.

Eventually this should be cleaned up and integrated with Twisted as
general auth support for twisted.web.xmlrpc.

$Id: xmlrpc.py 1660 2005-07-15 07:14:57Z tjs $
"""
# vi:ts=4 tw=80

import base64, urlparse, xmlrpclib
from twisted.internet import reactor
from twisted.web import xmlrpc

class QueryProtocol(xmlrpc.QueryProtocol):
    def connectionMade(self):
        self.sendCommand('POST', self.factory.url)
        self.sendHeader('User-Agent', 'Twisted/XMLRPClib')
        self.sendHeader('Host', self.factory.host)
        if self.factory.authString is not None:
            cred = base64.encodestring(self.factory.authString)
            self.sendHeader('Authorization', 'Basic ' + cred[:-1])
        self.sendHeader('Content-type', 'text/xml')
        self.sendHeader('Content-length', str(len(self.factory.payload)))
        self.endHeaders()
        self.transport.write(self.factory.payload)

class QueryFactory(xmlrpc.QueryFactory):
    protocol = QueryProtocol
    def __init__(self, url, host, method, authString=None, *args):
        self.authString = authString
        xmlrpc.QueryFactory.__init__(self, url, host, method, *args)

# rape'n'paste from twisted.web.xmlrpc.Proxy.
# "#!" means modified from original.
class Proxy:
    """A Proxy for making remote XML-RPC calls.

    Pass the URL of the remote XML-RPC server to the constructor.

    Use proxy.callRemote('foobar', *args) to call remote method
    'foobar' with *args.
    """

    def __init__(self, url):
        parts = urlparse.urlparse(url)
        self.url = urlparse.urlunparse(('', '')+parts[2:])
        self.auth = None #!
        if self.url == "":
            self.url = "/"
        if ':' in parts[1]:
            #! vvv
            if '@' in parts[1]:
                self.auth, address = parts[1].split('@')
            else:
                address = parts[1]
                self.authHost = None
            self.host, self.port = address.split(':')
            if self.auth is not None:
                self.authHost = '@'.join([self.auth, self.host])
            #! ^^^
            self.port = int(self.port)
        else:
            self.host, self.port = parts[1], None
        self.secure = parts[0] == 'https'

    def callRemote(self, method, *args):
        factory = QueryFactory(self.url, self.host,
                               method, self.auth, *args) #!
        if self.secure:
            from twisted.internet import ssl
            reactor.connectSSL(self.host, self.port or 443,
                               factory, ssl.ClientContextFactory())
        else:
            reactor.connectTCP(self.host, self.port or 80, factory)
        return factory.deferred





More information about the Twisted-web mailing list