home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomePHP CookbookSearch this book

12.8. Receiving XML-RPC Requests

12.8.3. 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 Recipe 12.7.

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 8601-formatted string with the current date and time. We escape the T inside the call to date( ) because the specification requires a literal T to divide the date part and the time part. For 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');

We create a new server and assign it to $server, 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.

We 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 we 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 Recipe 12.7, 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, we 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, we 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.

12.8.4. See Also

Recipe 12.7 for more information about XML-RPC clients; documentation on xmlrpc_server_create( ) 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.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.