Разработчику. Сборник рецептов PHP
Задавайте вопросы

Прием запросов XML-RPC

Вернуться назад

Задача

] Необходимо создать сервер XML-RPC и отвечать на XML-RPC-запросы. Это позволит клиенту, поддерживающему формат XML-RPC, задавать вашему серверу вопросы, а вам посылать в ответ данные.

Решение

Используйте PHP-расширение XML-RPC. Ниже приведена PHP-версия демонстрационного XML-RPC приложения фирмы Userland, которое возвращает строку стандарта ISO 8601 с текущей датой и временем:

// это функция, подставляемая как "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);

Обсуждение

Поскольку встроенное расширение XML-RPC, xmlrpc-epi, написано на C, оно обрабатывает XML-RPC-запросы быстрее и эффективнее. Чтобы подключить это расширение, добавьте к конфигурационной строке во время компиляции параметр --with-xmlrpc. Более подробную информацию о XML-RPC см. в рецепте (Посылка запросов XML-RPC).

Решение начинается с определения функции PHP, предназначенной для связи с методом XML-RPC. Имя функции – return_time(). Эта функция связывается с методом XML-RPC get_time():

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

}

Функция возвращает строку стандарта ISO 8601 с текущей датой и временем. Мы преобразуем символ T внутри вызова функции date() в escape-последовательность, т. к.к спецификация требует литерал T для разделения даты и времени. Для 21 августа 2002 года в 3:03:51 P.M. возвращаемое значение будет равно 20020821T150351.

Функция автоматически вызывается с двумя параметрами: именем метода XML-RPC, которому отвечает сервер, и массивом аргументов метода, передаваемым серверу XML-RPC-клиентом. В данном примере сервер игнорирует обе переменные.

Затем создаем сервер XML-RPC и регистрируем нужный метод –get_time():

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

Мы создали новый сервер и присвоили его переменной $server. Затем вызываем функцию xmlrpc_server_register_method() с тремя параметрами. Первый – это вновь созданный сервер, второй – имя регистрируемого метода, а третий – имя функции PHP, обрабатывающей запрос.

Теперь, когда все сконфигурировано, отдаем серверу команду вызвать обрабатывающий метод и вернуть результаты клиенту:

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

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

Данные клиентского запроса приходят методом POST. PHP конвертирует HTTP POST-данные в соответствующие переменные, но это XML-RPC-данные, и поэтому серверу необходим доступ к непроанализированным данным, хранящимся в переменной $GLOBALS['HTTP_RAW_POST_DATA']. В данном примере XML-запрос выглядит следующим образом:

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

Таким образом, сервер обращается к методу get_time(), и метод не ожидает никаких параметров.

Мы также настраиваем параметры ответа, чтобы выводить результаты в виде XML и интерпретировать запрос как XML-RPC. Эти две переменные затем передаются методу xmlrpc_server_call_method() вместе с XML-RPC-сервером $server. Третьим параметром может быть любая пользовательская информация, которую нужно передать. В данном случае она отсутствует, поэтому мы передаем ULL.

Функция xmlrpc_server_call_method() декодирует переменные, вызывает соответствующую функцию для реализации метода и кодирует ответ в формате XML-RPC. Чтобы отправить ответ клиенту, нужно всего лишь вывести возвращаемый методом xmlrpc_server_call_method() результат.

Наконец, мы завершаем работу вызовом функции:

xmlrpc_server_destroy($server);

Используя клиентскую XML-RPC-программу из рецепта (Посылка запросов XML-RPC), можно послать запрос и определить время так, как это показано ниже:

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.

Разрешается связывать несколько методов с одним XML-RPC-сервером. Можно также связать несколько методов с одной и той же функцией PHP. Например, мы создаем сервер, который отвечает двум методам: get_gmtime() и get_time(). Первый метод, get_gmtime(), подобен методу get_time(), но выдает в ответ текущее время в зоне GMT. Чтобы справиться с этой ситуацией, можно расширить метод get_time() для приема необязательного параметра – названия временной зоны, который будет использован при вычислении текущего времени.

Ниже показано, как изменить функцию return_time() для работы с обоими методами:

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'); } // меняем EST5EDT на зону вашего
                                                                          // сервера

return $date;

}

Эта функция использует и параметр $method, и параметр $args. В начале функции проверяется, использует ли запрос метод get_gmtime. Если это так, то в качестве временной зоны выбирается зона GMT. Если нет, то устанавливается альтернативная временнбя зона, определяемая путем проверки элемента $args[0]. Если ни одна из проверок не возвращает значение true, сохраняется текущая временная зона.

Чтобы сконфигурировать сервер для работы с новым методом, добавляем только одну новую команду:

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

Она связывает метод get_gmtime() с функцией return_time().

Ниже приведен пример действий клиента. Первый запрос – с использованием метода get_time() без параметров; второй запрос вызывает метод get_time() с временной зоной PST8PDT, которая отстает от времени сервера на три часа; последний запрос использует новый метод get_gmtime(), который опережает временную зону сервера на четыре часа.

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.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования

Рейтинг Сайтов ДОСКИ.РУ