July 1, 2008 · No comment · Filed under Webdev · Bookmark

The pursuit of APIness (part 4)

Last week we reviewed the principles behind a RESTful architecture. This week, as part 4 of this series dedicated to web APIs, we will focus on XML-RPC which, contrary to REST, is not a set of general principles but a substantial specification on how to format XML messages carried over HTTP.

Part 4: Review of XML-RPC

XML-RPC stands for XML Remote Procedure Call: a XML-RPC request is a HTTP POST request which body is formatted in XML and a XML-RPC response is a XML file sent back by the server. Contrary to REST, the method called by a XML-RPC request does not appear in the URL but appears in the XML POST body of the request, in-between tags <methodName>. Therefore, XML-RPC works based on a single entry point which is the unique URL to be called when using XML-RPC.

Before we dive into the XML-RPC specifications, here is how our favorite call (Joe’s call) to community.com’s API could be designed:

POST /xmlrpc HTTP/1.1
Host: api.community.com
User-agent: script
Content-type: text/xml
Content-length: 243

<?xml version="1.0"?>
<methodCall>
  <methodName>community.members.getList</methodName>
  <params>
    <param><value><int>23</int></value></param>
    <param><value><string>Indianapolis</string></value></param>
  </params>
</methodCall>

Note: several details matter in this sample request. First, we decided to use http://api.community.com/xmlrpc/ as the single entry point. Then, XML-RPC requires a User-agent (can be the name of the library you’re using, the name of your script or the name of your dog :) ) and a Content-type set to text/xml. Last, method names must be unique: had we simply called this method getList, we could have faced difficulties when designing the call to retrieve, for example, cities instead of members. This is why we prepended the method name with community.members so as to be aware that we are using community.com’s API and that we are looking for members.

And here would be the successful response:

HTTP/1.1 200 OK
Date: Tue, 01 Jul 2008 15:22:00 GMT
Content-Length: 313
Content-Type: text/xml
Connection: close

<?xml version="1.0"?>
<methodResponse>
  <params>
    <param>
      <value>
        <array>
          <data>
            <value><string>Anna</string></value>
            <value><string>Lisa</string></value>
          </data>
        </array>
      </value>
    </param>
  </params>
</methodResponse>

Now if we assume there was some issues while transmitting or processing the request, here is how an error response could be formatted:

HTTP/1.1 200 OK
Date: Tue, 01 Jul 2008 15:22:00 GMT
Content-Length: 384 
Content-Type: text/xml
Connection: close

<?xml version="1.0"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>1</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string>Invalid request.</string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>

Note: there is no official specification for error codes and error messages. Each API designer should conscientiously create error codes and error messages for each possible scenario. Still, I could find one attempt to make error codes more official on this webpage.

This is typical of a XML-RPC protocol: instead of relying on an existing standard, XML-RPC adds a new abstraction layer. A RESTful approach would have used the HTTP status tool (namely: a HTTP/1.1 400 Bad Request) to notify the client that the request didn’t work; instead, the XML-RPC approach clearly overwrites HTTP and puts the error message in the very XML response delivered. As a matter of fact, the HTTP status of the response is still HTTP/1.1 200 OK even though the request resulted in a failure.

The three examples above illustrate how XML-RPC looks like both in terms of requests and responses. The underlying structure is easy to guess: a request has to be contained between <methodCall> tags and specify both the <methodName> and optional <params> (parameters). Symmetrically, a response must be contained between <methodResponse> tags and speficy optional <params>. Parameters are contained in-between <params> tags and each parameter must be surrounded by <param> and <value> tags, and then tags corresponding to their data type. For example, an integer parameter will be sent like this: <param><value><int>23</int></value></param>.

XML-RPC defines several types of vanilla data types:

  • int or i4: 32-bit integers (e.g. <int>23</int> or <i4>23</i4>)
  • double: 64-bit floating-point numbers (e.g. <double>2.7812</double>)
  • boolean: boolean (true (1) or false (0): e.g. <boolean>1</boolean>)
  • string: ASCII or Unicode text (e.g. <string>Hello World!</string>)
  • dateTime.iso8601: a datetime (e.g. <dateTime.iso8601>20080701T15:22:00</dateTime.iso8601>)
  • base64: some base64-encoded information (e.g. <base64>SGVsbG8gV29ybGQh</base64>)

And two types of elaborated data types:

  • array: as shown in the “sample successful response” above, arrays further enclose data in <data> tags with as many <value> sub-items as there are values in the array (together with their data types)
  • struct: as shown in the “sample failure response” above, structured data is made of <members>, each of them having a <name> and a <value> with a specific data type (a bit like an associative array in PHP)

Note: both struct and array elements are recursive (I.e. a struct element can contain an array containing struct elements etc.): this opens endless possibilities for data formatting.

Programmatically speaking, creating XML-RPC clients and servers using PHP and relying on cURL and SimpleXML is absolutely not more complicated than the numerous code snippets explained in parts 1, 2 and 3. Only the XML syntax changes. Also note that there is a specific PHP extension for using XML-RPC (more information on php.net).

The pursuit of APIness continues next week with a quick review of XML-RPC’s successor: SOAP.

(go to Part 5: SOAP: Hot or not?)

Entries (RSS) Did you enjoy this post? Consider subscribing to the RSS feed!
SPREAD THE BUZZ

No comment so far.

Leave a comment