Search code examples
pythonxml-rpccherrypy

How to do XMLRPC with CherryPy


Server (CherryPy 3.2.0):

import cherrypy

class XMLRPCServer(cherrypy._cptools.XMLRPCController):
    def index(self):
        return 'index'
    index.exposed = True

if __name__ =='__main__':
    cherrypy.config.update({
        'server.thread_pool': 1,
        'request.dispatch': cherrypy.dispatch.XMLRPCDispatcher,
        'tools.xmlrpc.on': True,
        'tools.xmlrpc.allow_none': 0, 
    })
    cherrypy.quickstart(XMLRPCServer())

Client (Python 2.7.1):

import xmlrpclib
svc = xmlrpclib.ServerProxy('http://127.0.0.1:8080')
r = svc.index()

Error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/xmlrpclib.py", line 1224, in __call__
    return self.__send(self.__name, args)
  File "/usr/lib/python2.7/xmlrpclib.py", line 1575, in __request
    verbose=self.__verbose
  File "/usr/lib/python2.7/xmlrpclib.py", line 1264, in request
    return self.single_request(host, handler, request_body, verbose)
  File "/usr/lib/python2.7/xmlrpclib.py", line 1312, in single_request
    response.msg,
xmlrpclib.ProtocolError: <ProtocolError for 127.0.0.1:8080/RPC2: 404 Not Found>

How do you enable xml-rpc in CherryPy, I've googled and read the docs but still stuck.


Solution

  • Here's relavant quote from XMLRPCController documentation:

    The XMLRPCDispatcher strips any /RPC2 prefix; if you aren’t using /RPC2 in your URL’s, you can safely skip turning on the XMLRPCDispatcher.

    The following works fine. Also pay attention to separating global and application configuration, as you've mixed them up.

    sever.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import cherrypy
    
    
    config = {
      'global' : {
        'server.socket_host' : '127.0.0.1',
        'server.socket_port' : 8080,
        'server.thread_pool' : 8
      },
      '/' : {
        'tools.xmlrpc.allow_none' : True
      }
    }
    
    
    class Api(cherrypy._cptools.XMLRPCController):
    
      @cherrypy.expose
      def mul(self, a, b):
        return a * b
    
    
    if __name__ == '__main__':
      cherrypy.quickstart(Api(), '/api', config)
    

    client.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import xmlrpclib
    
    
    rpc = xmlrpclib.ServerProxy('http://localhost:8080/api')
    print rpc.mul(2, 6)