0

Let's have a simple xmlrpc server defined as in the following code:

from SimpleXMLRPCServer import SimpleXMLRPCServer

def add(x,y):
    return x+y

server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(add, 'addthem')
server.register_function(add, 'add.numbers')
server.register_function(add, 'sum.two.numbers')
server.serve_forever()

which you can connect to via

import xmlrpclib
dev = xmlrpclib.ServerProxy("http://localhost:8000/RPC2")

With the dev object, you cann access the (for reasons of simplicity same) function add in the server, like

print dev.addthem(1,2)
print dev.add.numbers(1,2)
print dev.sum.two.numbers(1,2)

My question: What are the pieces of those calls? What is dev (I suppose an instance of xmlrpclib.ServerProxy), what is sum in dev.sum (a function? a callable? a class? an instance?). What is two in dev.sum.two ...

For example, the following syntax

print dev.add

results in an error

xmlrpclib.Fault: <Fault 1: '<type \'exceptions.Exception\'>:method "add.__str__" is not supported'>

Shouldn't that print something always? What is dev.add and the other pieces?

Alex
  • 41,580
  • 88
  • 260
  • 469
  • Where can I find information about those xmlrpc function? Why can't I print them? What attributes do they have? Why can't I do a `dir` of them? – Alex Dec 09 '12 at 09:11
  • `xmlrpclib.ServerProxy` sources might be a good start. But why do you need to know that? –  Dec 09 '12 at 09:13
  • Are you looking for an explanation of the XML-RPC protocol, or how the `xmlrpclib` library implements it's API? – Martijn Pieters Dec 09 '12 at 09:14
  • Because I need to be able to trace any calls to the xmlrpc server. For example, whan I do a call `dev.sum.two.numbers(1,2)` I need to be able to log the exact request, i.e. to be able to reconstruct the full sequence `dev.sum.two.numbers(1,2)`. I started to overwrite the `__getattr__` function, but this does not seem to work. – Alex Dec 09 '12 at 09:15
  • I guess I need the xmlrpc API. Any good one your know of? For example, I have figured out that `dev.add` for example has two keys `_Method__name` and `_Method__send`. But what are these things? – Alex Dec 09 '12 at 09:23

2 Answers2

1

In order to "log" requests, you could (for example) implements a custom Transport in your client.

From the doc (adapted):

import xmlrpclib, httplib, gzip

class LogTransport(xmlrpclib.Transport):
    def send_request(self, connection, handler, request_body):
        # log here.
        print handler, request_body
        if (self.accept_gzip_encoding and gzip):
            connection.putrequest("POST", handler, skip_accept_encoding=True)
            connection.putheader("Accept-Encoding", "gzip")
        else:
            connection.putrequest("POST", handler)

p = LogTransport()
server = xmlrpclib.Server('http://time.xmlrpc.com/RPC2', transport=p)
print server.currentTime.getCurrentTime()

Output:

/RPC2 <?xml version='1.0'?>
<methodCall>
<methodName>currentTime.getCurrentTime</methodName>
<params>
</params>
</methodCall>

and a server error (because it doesn't exists)

  • This is interesting! I need to check further, but so far it seems promising. Thanks a lot. – Alex Dec 09 '12 at 09:35
0

In this case, sum.two.numbers is just the function to be called on the server. On this line server.register_function(add, 'sum.two.numbers') you are setting that method to map to the add function which takes 2 arguments. All of your server's available methods are mapped to add currently. dev.add is just telling the client to run the method add on the server. Because you do not map add to the actual function on the server, you cannot use it and an error is thrown.

Check out this example which includes a custom SimpleXMLRPCRequestHandler where you can customize it to add logging.

Take a look at this if you are still having problems with the logging: XML-RPC server logging

Community
  • 1
  • 1
Ngenator
  • 10,909
  • 4
  • 41
  • 46