Serving an XML-RPC Method






Serving an XML-RPC Method

Problem

You want to create an XML-RPC server and respond to XML-RPC requests. This allows any XML-RPC-enabled client to ask your server questions and you to reply with data.

Solution

Use PHP's XML-RPC extension. Here is a PHP version of the Userland XML-RPC demonstration application that returns an ISO 8601 string with the current date and time:

// this is the function exposed as "get_time()"
function return_time($method, $args) {
   return date('Ymd\THis');
}

$server = xmlrpc_server_create() or die("Can't create server");
xmlrpc_server_register_method($server, 'return_time', 'get_time')
    or die("Can't register method.");

$request = $GLOBALS['HTTP_RAW_POST_DATA'];
$options = array('output_type' => 'xml', 'version' => 'xmlrpc');

print xmlrpc_server_call_method($server, $request, NULL, $options)
    or die("Can't call method");

xmlrpc_server_destroy($server);

Discussion

Since the bundled XML-RPC extension xmlrpc-epi is written in C, it processes XML-RPC requests in a speedy and efficient fashion. Add --with-xmlrpc to your configure string to enable this extension during compile time. For more on XML-RPC, see 14.12.

The Solution begins with a definition of the PHP function to associate with the XML-RPC method. The name of the function is return_time( ) . This is later linked with the get_time( ) XML-RPC method:

function return_time($method, $args) {
   return date('Ymd\THis');
}

The function returns an ISO 8601formatted string with the current date and time. Escape the T inside the call to date( ) because the specification requires a literal T to divide the date part and the time part. At August 21, 2002 at 3:03:51 P.M., the return value is 20020821T150351.

The function is automatically called with two parameters: the name of the XML-RPC method the server is responding to and an array of method arguments passed by the XML-RPC client to the server. In this example, the server ignores both variables.

Next, create the XML-RPC server and register the get_time( ) method:

$server = xmlrpc_server_create() or die("Can't create server");
xmlrpc_server_register_method($server, 'return_time', 'get_time');

Create a new server and assign it to $server and then call xmlrpc_server_register_method( ) with three parameters. The first is the newly created server, the second is the name of the method to register, and the third is the name of the PHP function to handle the request.

Now that everything is configured, tell the XML-RPC server to dispatch the method for processing and print the results to the client:

$request = $GLOBALS['HTTP_RAW_POST_DATA'];
$options = array('output_type' => 'xml', 'version' => 'xmlrpc');

print xmlrpc_server_call_method($server, $request, NULL, $options);

The client request comes in as POST data. PHP converts HTTP POST data to variables, but this is XML-RPC data, so the server needs to access the unparsed data, which is stored in $GLOBALS['HTTP_RAW_POST_DATA']. In this example, the request XML looks like this:

<?xml version="1.0" encoding="iso-8859-1"?>
<methodCall>
<methodName>get_time</methodName>
<params/></methodCall>

Thus, the server is responding to the get_time( ) method, and it expects no parameters.

You must also configure the response options to output the results in XML and interpret the request as XML-RPC. These two variables are then passed to xmlrpc_server_call_method( ) along with the XML-RPC server, $server. The third parameter to this function is for any user data you wish to provide; in this case, there is none, so pass NULL.

The xmlrpc_server_call_method( ) function decodes the variables, calls the correct function to handle the method, and encodes the response into XML-RPC. To reply to the client, all you need to do is print out what xmlrpc_server_call_method( ) returns.

Finally, clean up with a call to xmlrpc_server_destroy( ):

xmlrpc_server_destroy($server);

Using the XML-RPC client code from 14.12, you can make a request and find the time, as follows:

require 'utils.php';

$output = array('output_type' => 'xml', 'version' => 'xmlrpc');
$result = xu_rpc_http_concise(array(
                             'method'  => 'get_time',
                             'host'    => 'clock.example.com',
                             'port'    => 80,
                             'uri'     => '/time-xmlrpc.php',
                             'output'  => $output));

print "The local time is $result.\n";

The local time is 20020821T162615.

It is legal to associate multiple methods with a single XML-RPC server. You can also associate multiple methods with the same PHP function. For example, you can create a server that replies to two methods: get_gmtime( ) and get_time( ). The first method, get_gmtime( ), is similar to get_time( ), but it replies with the current time in GMT. To handle this, you can extend get_time( ) to take an optional parameter, which is the name of a time zone to use when computing the current time.

Here's how to change the return_time( ) function to handle both methods:

function return_time($method, $args) {
    if ('get_gmtime' == $method) {
        $tz = 'GMT';
    } elseif (!empty($args[0])) {
        $tz = $args[0];
    } else {
        // use local time zone
        $tz = '';
    }

    if ($tz) { putenv("TZ=$tz"); }
    $date = date('Ymd\THis');
    if ($tz) { putenv('TZ=EST5EDT'); } // change EST5EDT to your server's zone

    return $date;
}

This function uses both the $method and $args parameters. At the top of the function, we check if the request is for get_gmtime. If so, the time zone is set to GMT. If it isn't, see if an alternate time zone is specified as an argument by checking $args[0]. If neither check is TRue, keep the current time zone.

To configure the server to handle the new method, add only one new line:

xmlrpc_server_register_method($server, 'return_time', 'get_gmtime');

This maps get_gmtime( ) to return_time( ).

Here's an example of a client in action. The first request is for get_time( ) with no parameters; the second calls get_time( ) with a time zone of PST8PDT, which is three hours behind the server; the last request is for the new get_gmtime( ) method, which is four hours ahead of the server's time zone:

require 'utils.php';

$output = array('output_type' => 'xml', 'version' => 'xmlrpc');

// get_time()
$result = xu_rpc_http_concise(array(
                             'method'  => 'get_time',
                             'host'    => 'clock.example.com',
                             'port'    => 80,
                             'uri'     => '/time.php',
                             'output'  => $output));

print "The local time is $result.\n";

// get_time('PST8PDT')
$result = xu_rpc_http_concise(array(
                             'method'  => 'get_time',
                             'args'    => array('PST8PDT'),
                             'host'    => 'clock.example.com',
                             'port'    => 80,
                             'uri'     => '/time.php',
                             'output'  => $output));

print "The time in PST8PDT is $result.\n";

// get_gmtime()
$result = xu_rpc_http_concise(array(
                             'method'  => 'get_gmtime',
                             'host'    => 'clock.example.com',
                             'port'    => 80,
                             'uri'     => '/time.php',
                             'output'  => $output));

print "The time in GMT is $result.\n";

The local time is 20020821T162615.
The time in PST8PDT is 20020821T132615.
The time in GMT is 20020821T202615.

See Also

14.12 for more information about XML-RPC clients; documentation on xmlrpc_server_create( ) can be found at http://www.php.net/xmlrpc-server-create, xmlrpc_server_register_method( ) at http://www.php.net/xmlrpc-server-register-method, xmlrpc_server_call_method( ) at http://www.php.net/xmlrpc-server-call-method, and xmlrpc_server_destroy( ) at http://www.php.net/xmlrpc-server-destroy; Programming Web Services with XML-RPC by Simon St.Laurent, Joe Johnston, and Edd Dumbill (O'Reilly); more on XML-RPC at http://www.xml-rpc.com; the original current time XML-RPC server at http://www.xmlrpc.com/currentTime.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows