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';
function getImage()
{
if($img = @file_get_contents('graph.png'))
{
$val = new XML_RPC_Value($img, 'base64');
return new XML_RPC_Response($val);
}
return new XML_RPC_Response(0, $XML_RPC_erruser+1,
'There was an error opening the file.');
}
$server = new XML_RPC_Server(
array(
'getPhoto' =>
array('function' => 'getImage'),
)
);
?>
client.php:
<?php
require_once 'XML/RPC.php';
$msg = new XML_RPC_Message('getPhoto');
$cli = new XML_RPC_Client('/xml-rpc/server.php', 'localhost');
$cli->setDebug(0);
$resp = $cli->send($msg);
if (!$resp)
{
echo 'Communication error: ' . $cli->errstr;
exit;
}
if (!$resp->faultCode())
{
$val = $resp->value();
header('Content-type: image/png');
echo $val->scalarval();
}
else
{
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.