Using XML-RPC and Base64 encoded binary data

I’ve been looking at ways to improve the performance of the new BritBlog server, and wherever possible I try to use components from the PHP Extension and Application Repository (PEAR).

For example, I’ve found PEAR Cache_Lite to be an excellent tool for caching dynamic content that doesn’t change that frequently, and I use things like XML_Tree and XML_RSS when handling XML and RSS.

What about XML RPC?

So in my quest to remove load from the server I’ve been looking into the possibility of generating dynamic images (maps and graphs, for example) off-site, and then transferring them to the server over XML RPC, using the PEAR XML_RPC package.

So is it possible? The short answer is ‘Yes’! The trick is to base64 encode the image data. You can either do this with the PHP base64_encode() method, and then specify the XML-RPC data type of string, or you can specify the data type of base64 and let XML-RPC take care of the encoding itself.

A note on base64 encoding from the PHP manual:

base64_encode() returns data encoded with base64. This encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies.

Base64-encoded data takes about 33% more space than the original data.

As Base64 is a supported data type for XML-RPC then this should be used by preference. Setting the data type to Base64 also makes the encoding happen transparently, which means there is one less thing for you to worry about.

So here is are two little scripts to demonstrate this, using the PEAR XML_RPC package. (They are based heavily on the example scripts in the documentation.) Create two files, server.php and client.php and stick the in a folder called xml-rpc in the root directory of a web server. Now copy the code below into the two files.

Now if you open http://localhost/xml-rpc/client.php (assuming you are running the web server locally), the client will make the request to the web service getImage and then print the image that is returned to your screen.

server.php:

<?php
require_once 'XML/RPC/Server.php';

/*
 * Method to return an image. Perhaps this
 * generates an image on-the-fly.
 */
function getImage()
{
   // We're just going to open an existing image
   if($img = @file_get_contents('graph.png'))
   {
      $val = new XML_RPC_Value($img, 'base64');
      return new XML_RPC_Response($val);
   }

   // Ooops, couldn't open the file so return an error message.
   return new XML_RPC_Response(0, $XML_RPC_erruser+1, // user error 1
			      'There was an error opening the file.');
}

// map web services to methods
$server = new XML_RPC_Server(
   array(
      'getPhoto' =>
         array('function' => 'getImage'),
   )
);
?>

client.php:

<?php
require_once 'XML/RPC.php';

$msg = new XML_RPC_Message('getPhoto'); // getPhoto is the service we want to call

$cli = new XML_RPC_Client('/xml-rpc/server.php', 'localhost');
$cli->setDebug(0);

// send the request message
$resp = $cli->send($msg);

if (!$resp)
{
   echo 'Communication error: ' . $cli->errstr;
   exit;
}

if (!$resp->faultCode())
{
   // All OK, so print the image
   $val = $resp->value();
   header('Content-type: image/png');
   echo $val->scalarval();
}
else
{
   /*
    * Display problems that have been gracefully cought and
    * reported by the xmlrpc.php script.
    */
   echo 'Fault Code: ' . $resp->faultCode() . "n";
   echo 'Fault Reason: ' . $resp->faultString() . "n";
}
?>

So there you have it. As is common with code using PEAR packages, it’s nice and simple!

I’m not sure if I’ll start using this kind of stuff for BritBlog, but it shows an interesting application for XML-RPC.

Sociable:These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • digg
  • Furl
  • NewsVine
  • Reddit
  • YahooMyWeb

3 Responses to “Using XML-RPC and Base64 encoded binary data

Leave a Reply