Прием запросов 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 см. в рецепте 12.6.

Решение начинается с определения функции 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-данные в соответствующие переменные, но это XMLRPC-данные, и поэтому серверу необходим доступ к непроанализированным данным, хранящимся в переменной $GLOBALS['HTTP_RAW_POST_DATA'].

В данном примере XML-запрос выглядит следующим образом:



get_time


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

Мы также настраиваем параметры ответа, чтобы выводить результаты в виде XML и интерпретировать запрос как XML-RPC.


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

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

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

xmlrpc_server_destroy($server);

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

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.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Анализ XML с помощью DOM
Анализ XML с помощью SAX
Генерация XML вручную
Генерация XML с применением DOM
Обмен данными с помощью WDDX

Вернуться в раздел: PHP / 12. XML