[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