Search code examples
pythonxml-rpcxmlrpclibunix-socket

Use Python xmlrpclib with unix domain sockets?


I'm trying to interact with supervisord, and I'd like to talk with it over a unix socket (it's a shared hosting environment).

What I've tried so far is:

import xmlrpclib
server = xmlrpclib.ServerProxy('unix:///path/to/supervisor.sock/RPC2')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/xmlrpclib.py", line 1549, in __init__
    raise IOError, "unsupported XML-RPC protocol"
IOError: unsupported XML-RPC protocol

/path/to/supervisor.sock definitely exists. URIs of the form 'unix:///path/to/supervisor.sock/RPC2' are used by supervisord, which is where I got the idea. The docs don't discuss unix sockets: http://docs.python.org/library/xmlrpclib.html.

Is this possible? Should I use a different library?


Solution

  • xmlrpclib requires that the url passed start with http or https. The way around this is to define a custom transport which ignores that url. Here's some code using the transport from supervisor:

    import supervisor.xmlrpc
    import xmlrpclib
    
    proxy = xmlrpclib.ServerProxy('http://127.0.0.1',
                                   transport=supervisor.xmlrpc.SupervisorTransport(
                                        None, None, serverurl='unix://'+socketpath))
    
    proxy.supervisor.getState()
    

    In case that's not useful, here's an updated version of the code found here:

    class UnixStreamHTTPConnection(httplib.HTTPConnection, object):
        def __init__(self, *args, **kwargs):
            self.socketpath = kwargs.pop('socketpath')
            super(UnixStreamHTTPConnection, self).__init__(*args, **kwargs)
    
        def connect(self):
            self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            self.sock.connect_ex(self.socketpath)
    
    class UnixStreamTransport(xmlrpclib.Transport, object):
        def __init__(self, *args, **kwargs):
            self.socketpath = kwargs.pop('socketpath')
            super(UnixStreamTransport, self).__init__(*args, **kwargs)