This article is a quick introduction to how the Nucleus XML-RPC server works. Such an XML-RPC server is basically a PHP script that accepts an XML request, performs some actions and then answers in XML as well.
(Since a draft version of this article has been on my desktop for over a month, I decided to just dump it here.)
Although recent versions of PHP often include built-in XML-RPC support, not all versions do. Therefore, Nucleus is using the XML-RPC for PHP library from Useful Inc.
The server.php is straightforward: next to defining some helper methods, it included the api_xxxx.inc.php files, and then creates a new xmlrpc_server($functionDefs) object. That's all it takes.
The $functionDefs variable is filled out by the api_xxxx.inc.php files, and is an array of all possible actions. For each allowed action, three pieces of information are required:
-
A method signature. Or: how the XML request must be built and what the answer will look like. For example, the
blogger.newPostcall requires 5 strings (appkey, blogid, user, pwd, post content) and a boolean (publish now/create draft?) -
A string with documentation for the action. This info is returned in the
system.listMethodsaction, which exists by default in the XML-RPC server. -
The name of a method that will handle the request. This method will get called by the server class, with an
xmlrpcmsgobject being passed as parameter. The method needs to return anxmlrpcrespobject, which will be sent back to the client.
An example is given below: (taken from api_blogger.inc.php)
// blogger.newPost
$f_blogger_newPost_sig = array(array(
// return type
$xmlrpcString, // itemid of the new item
// params:
$xmlrpcString, // appkey (ignored)
$xmlrpcString, // blogid
$xmlrpcString, // username
$xmlrpcString, // password
$xmlrpcString, // content
$xmlrpcBoolean, // publish boolean (set to false to create draft)
));
$f_blogger_newPost_doc = "Adds a new item to the given blog. Adds it as a draft when publish is false";
function f_blogger_newPost($m) {
$blogid = _getScalar($m,1);
$username = _getScalar($m,2);
$password = _getScalar($m,3);
$content = _getScalar($m,4);
$publish = _getScalar($m,5);
$title = blogger_extractTitle($content);
$category = blogger_extractCategory($content);
$content = blogger_removeSpecialTags($content);
return _addItem($blogid, $username, $password, $title, $content, '', $publish, 0, $category);
}
$functionDefs = array_merge($functionDefs,
array(
"blogger.newPost" =>
array( "function" => "f_blogger_newPost",
"signature" => $f_blogger_newPost_sig,
"docstring" => $f_blogger_newPost_doc),
"blogger.editPost" =>
array( "function" => "f_blogger_editPost",
"signature" => $f_blogger_editPost_sig,
"docstring" => $f_blogger_editPost_doc),
...
)
);
The
$xmlrpcStringand$xmlrpcBooleanvariables are defined by the XML-RPC for PHP class.Methods like
_getScalarare defined inserver.php. The purpose is to make reading the request parameters easier.
There are some small things to keep in mind when editing code:
-
To perform actions, the code makes calls to other classes (e.g.
ITEM::update,BLOG::additem, ...). Since the XML-RPC server eats XML and is supposed to respond an XML response, no redirects, HTML or PHP warnings should be written to the output from inside this code. -
While developing it's hard to build the response in the correct way, since it's often a nested array of objects which in turn contain more nested arrays. Some insight in how XML-RPC works is a good thing. You only need to get it right once, though :)
Below is a (simplified) piece of code from
metaWeblog.getRecentPosts$structarray = array(); while ($row = mysql_fetch_assoc($r)) { $newstruct = new xmlrpcval(array( "dateCreated" => new xmlrpcval(iso8601_encode(strtotime($row['itime'])),"dateTime.iso8601"), "userid" => new xmlrpcval($row['iauthor'],"string"), "blogid" => new xmlrpcval($blogid,"string"), "postid" => new xmlrpcval($row['inumber'],"string"), "description" => new xmlrpcval($row['ibody'],"string"), "title" => new xmlrpcval($row['title'],"string"), "categories" => new xmlrpcval( array( new xmlrpcval($row['category'], "string") ) ,"array") ),'struct'); array_push($structarray, $newstruct); } return new xmlrpcresp(new xmlrpcval( $structarray , "array"));
Posted by karma at 17:22:35. Filed under: Inside Nucleus

Comments
Add Comment