XML-RPC: It Works Both Ways

In my previous XML-RPC article, I showed how to access the Meerkat XML-RPC server (written in PHP) from Python. This time around, we will go behind the scenes to view the structure of an XML-RPC method call and response. Then we will develop an XML-RPC server using Fredrick Lundh's xmlrpclib. Lastly, we'll touch on some real-world concerns about XML-RPC, SOAP, and look at the W3C's working group that is driving development of XML-based distributed application standardization.

A peek under the hood

So how does xmlrpclib work? Its approach to the construction of method calls and responses is quite simple. A method called dumps (dump string) turns native Python objects into XML. The process is called "marshalling". The reverse process, called "unmarshalling", is performed by loads (load string). Although transparent to the casual user, we can access these methods to peek under the hood. The dumps method takes three arguments: a tuple containing the parameters, the method name, and a method response. The last two are optional. Following good object-oriented design, xmlrpclib's dumps insists that the parameters are passed in the form of a tuple. This prevents modification of the parameters past this point.

Let's examine the structure of a method call used with Meerkat. At this point, no connection is needed. We are simply examining what will be sent, not actually communicating with a server.

Performing the reverse is even easier. To load an incoming XML-RPC response into a native Python object, simply use the loads method (load string). Extracting the first element of the tuple returned by loads will give us our original dictionary:

This process of dumping and then loading structures is useful to verify that your data is compatible with the present xmlrpclib.

Building an XML-RPC server

Now, let's turn to building an XML-RPC server to support a testing harness using dumps and loads. There are several good quality XML-RPC servers built in Python. Medusa comes with an implementation which Ng Pheng Siong has in turn included and enhanced in his excellent M2Crypto package for those who require a secure socket layer (SSL) transport mechanism. Zope, of course, comes with its own implementation of XML-RPC. For our purposes, we'll use Fredrick Lundh's example server as the base for our discussion. It is bundled with the client software we have been using, and is located in the file xmlrpcserver.py. This uses a method named call to hand off requests from clients to other methods or object instances.

First, we'll import the necessary packages:

import SocketServer
import xmlrpcserver
import xmlrpclib

Now, let's create a descendent of the RequestHandler class included in xmlrpcserver.py:

The core functionality of the method lies in server_method = getattr(self, method), which obtains a reference to the requested method if it is in the class. If the method doesn't exist, an attribute exception is raised, causing an XML-RPC Fault message to be returned to the client.

Now, let's add a dump_response() method that can marshall the response of a method call that doesn't already return marshalled data. First, we need a short method to test. The utility methods dump_method() and dump_params() are unsuitable since their responses are already marshalled. We need a test utility method that simply returns a Python object.

Armed with the above, it is simple to test your own methods and add them to the server. The only requirement of the above structure is that your entry point be a method of the TestRequestHandler class. The completed file with the test harness is located here.

After starting the server up in another process, we can connect and test the results:

The future of XML-RPC

For ease of use, xmlrpclib wins hands down for communicating with Meerkat. But does XML-RPC have a future? Yes! Athough the lure of wide-spread corporate backing is pushing many toward the Simple Object Access Protocol (SOAP), XML-RPC is in use today in some surprising places. Red Hat uses xmlrpclib.py in its new subscription service, and also internally. Their implementation of xmlrpclib ships with Red Hat 7 and includes enhancements by Cristian Gafton that include https support. Additionally, Userland's Frontier is fully XML-RPC aware, as is the Apache Java Project's Turbine framework and, by extension, Jetspeed.

So, where does that leave SOAP? Recently, the W3C established a working group on XML protocols. They have published a draft requirements document. Although they are using SOAP as their starting point, it is unlikely that SOAP will remain unchanged by this standardization process. I don't expect SOAP to go away any time soon, but I do expect it to be in flux for the next year or so.

Hopefully, the example above has shown that XML-RPC is not just a step on the way to SOAP and beyond, but a useful, simple tool in its own right. When XML-RPC was first introduced, Jon Udell asked the question: "Does distributed computing have to be any harder than this?" Much of the time, no.

Dave Warner
is a senior programmer and DBA at Federal Data Corporation. He specializes in accessing relational databases with languages that begin with the letter P: Python, Perl, and PowerBuilder.