Серверные классы XML-RPC и XML-RPCS 

Класы XML-RPC CodeIgniter позволяет отправлять запросы на другой сервер, или создать свой собственный XML-RPC сервер чтобы получать запросы.

Что такое XML-RPC? 

Довольно простой способ обмена данными между двумя компьютерами через интернет - использование XML. Компьютер, который отправляет XML-RPC запрос на другой компьютер, называется клиент. Принимающий запрос компьютер - сервер. Как только сервер получает и обрабатывает запрос, он отсылает назад ответ клиенту.

Например, с помощью MetaWeblog API, XML-RPC Клиент (обычно инструмент для публикаций) будет отправлять запрос на XML-RPC Сервер запущенный на вашем сайте. Этот запрос может являться новой записью блога, отправленной для публикации или это может быть запрос на редактирование существующующей записи. Когда XML-RPC Сервер получает этот запрос, он изучает его, чтобы определить, какие класс/метод должны быть вызваны для обработки запроса. После обработки сервер отправит обратно сообщение с ответом.

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

Использование XML-RPC класса 

Инициализация класса 

Как и большинство других классов CodeIgniter, классы XML-RPC и XML-RPCS инициализируется в вашем контроллере, используя функцию $this->load->library:

To load the XML-RPC class you will use:

$this->load->library('xmlrpc');

После загрузки, xml-rpc библиотека объектов будет доступна через: $this->xmlrpc

Для загрузки класса XML-RPC Сервера следует использовать:

$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');

После загрузки, xml-rpcs библиотека объектов будет доступна через: $this->xmlrpcs

Примечание

При использовании класса XML-RPC Сервера, следует загружать ОБА класса XML-RPC и the XML-RPC Сервер.

Отправка XML-RPC запросов 

Для отправки запроса XML-RPC серверу необходимо указать следующую информацию:

  • URL сервера
  • Метод на сервере, который вы хотите использовать
  • Данные запроса (объяснение ниже).

Вот простой пример, который отправляет простой Weblogs.com пинг на Ping-o-Matic

$this->load->library('xmlrpc');

$this->xmlrpc->server('http://rpc.pingomatic.com/', 80);
$this->xmlrpc->method('weblogUpdates.ping');

$request = array('My Photoblog', 'http://www.my-site.com/photoblog/');
$this->xmlrpc->request($request);

if ( ! $this->xmlrpc->send_request())
{
        echo $this->xmlrpc->display_error();
}

Объяснение 

Код выше инициализирует XML-RPC класс, с указанными URL сервера и методом для вызова (weblogUpdates.ping). Запрос (в нашем случае, заголовок и URL сайта) помещается в массив для отправки и компилируется функцией request(). Наконец, сформированный запрос будет отправлен. Если метод send_request() возвращает FALSE мы будет показано сообщение об ошибке отправленное XML-RPC Сервером.

Анатомия запроса 

XML-RPC запрос - просто данные для передачи XML-RPC серверу. Каждая часть данных в запросе упоминается как параметр запроса. Пример выше имеет два параметра: URL и заголовок вашего сайта. Когда XML-RPC сервер получает ваш запрос, он ищет параметры в нем.

Параметры запроса должны быть помещены в массив для отправки и каждый параметр может быть одним из семи типов данных (строка, число, дата и т.д.). Если параметры представляют собой нечто иное чем строки, вам придется включить тип данных в массив запроса.

Вот простой пример массива с тремя параметрами:

$request = array('John', 'Doe', 'www.some-site.com');
$this->xmlrpc->request($request);

При использовании типов данных отличных от строк или если у вас есть несколько различных типов данных, следует создать массив для каждого параметра с указанным типом данных на второй позиции:

$request = array(
        array('John', 'string'),
        array('Doe', 'string'),
        array(FALSE, 'boolean'),
        array(12345, 'int')
);
$this->xmlrpc->request($request);

В разделе ниже, предоставлены все типы данных.

Создание XML-RPC сервера 

XML-RPC Сервер действует как "гаишник", ожидает входящие запросы и перенаправляет их в соответствующие функции для обработки.

Создание собственного XML-RPC сервера включает инициализацию класса XML-RPC Сервера в вашем контроллере, где ожидается появление входящего запроса, затем создается массив с такими инструкциями отображения, чтобы входящие запросы могли быть отправлены в соответствующий класс и метод для обработки.

Вот пример для иллюстрации:

$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');

$config['functions']['new_post'] = array('function' => 'My_blog.new_entry');
$config['functions']['update_post'] = array('function' => 'My_blog.update_entry');
$config['object'] = $this;

$this->xmlrpcs->initialize($config);
$this->xmlrpcs->serve();

Пример выше содержит массив определяющий два метода запроса допустимые на сервере. Допустимые методы находятся в левой части массива. Когда любой из них будет получен, они будут сопоставлены классу и методам в правой части массива.

Ключ ‘object’ это специальный ключ, который вы передаете в объект класса, который необходим при выполнении сопоставления метода и он не является частью CodeIgniter супер объекта.

Другими словами, если XML-RPC Клиент отправляет запрос в new_post метод, ваш сервер загрузит класс My_blog и вызовет new_entry функцию. Если запрос в update_post метод, ваш сервер загрузит класс My_blog и вызовет метод update_entry().

Имена функции в примере выше являются произвольными. Вы сами решите как они должны называться на вашем сервере или если вы используете стандартизированный API, такие как Blogger или MetaWeblog API, вы будете использовать их имена функций.

Есть два дополнительных ключа для настройки, которые вы можете использовать при инициализации класса сервера: debug может быть установлен в TRUE для того, чтобы включить отладку и xss_clean может быть установлен в FALSE чтобы предотвратить отправку данных через метод xss_clean() библиотеки безопасности.

Обработка запросов сервером 

Когда XML-RPC Сервер получает запрос и загружает класс/метод для обработки, он передаст объект в метод содержащий данные отправленные клиентом.

В примере выше, если предлагается метод new_post, сервер будет ожидать существование класса с этим прототипом:

class My_blog extends CI_Controller {

        public function new_post($request)
        {

        }
}

Переменная $request - это объект, составленный сервером, который содержит данные, отправляемые XML-RPC клиентом. Используя этот объект, вы будете иметь доступ к параметрам запроса позволяющим обработать запрос. Когда все обработаете - будете отправлять ответ обратно клиенту.

Ниже приведен реальный пример Blogger API. Один из методов в Blogger API являеся getUserInfo(). С помощью этого метода XML-RPC клиент может послать серверу имя пользователя и пароль, а в ответ сервер отправляет обратно информацию о конкретном пользователь (nickname, user ID, email и т.д.). Вот как может выглядеть функция обработки:

class My_blog extends CI_Controller {

        public function getUserInfo($request)
        {
                $username = 'smitty';
                $password = 'secretsmittypass';

                $this->load->library('xmlrpc');

                $parameters = $request->output_parameters();

                if ($parameters[1] != $username && $parameters[2] != $password)
                {
                        return $this->xmlrpc->send_error_message('100', 'Invalid Access');
                }

                $response = array(
                        array(
                                'nickname'  => array('Smitty', 'string'),
                                'userid'    => array('99', 'string'),
                                'url'       => array('http://yoursite.com', 'string'),
                                'email'     => array('jsmith@yoursite.com', 'string'),
                                'lastname'  => array('Smith', 'string'),
                                'firstname' => array('John', 'string')
                        ),
                         'struct'
                );

                return $this->xmlrpc->send_response($response);
        }
}

Примечания: 

Метод output_parameters() возвращает индексированный массив соответствующий параметрам запроса отправленного клиентом. В приведенном выше примере параметрами вывода будут логин и пароль.

Если имя пользователя и пароль отправленные клиентом являются недействительными, возвращается сообщение об ошибке используя метод send_error_message().

Если операция была успешной, клиенту будет обратно отправлен массив содержащий информацию о пользователе.

Формат ответа 

Аналогично Запросам, Ответы должен быть в виде массива. Однако, в отличие от запросов, ответ это массив который содержит один элемент. Этот элемент может быть массивом с несколькими дополнительными массивами, но там может быть только один индекс первичного массива. Иными словами, прототип этого:

$response = array('Response data', 'array');

Однако ответы, содержат несколько фрагментов информации, как правило. Для этого мы должны вложить ответ в свой собственный массив таким образом, чтобы основной массив содержал отдельную часть данных. Вот пример, показывающий, как это может быть реализовано:

$response = array(
        array(
                'first_name' => array('John', 'string'),
                'last_name' => array('Doe', 'string'),
                'member_id' => array(123435, 'int'),
                'todo_list' => array(array('clean house', 'call mom', 'water plants'), 'array'),
        ),
        'struct'
);

Обратите внимание, что массив форматируется как строгий. Это наиболее распространенный тип данных для ответов.

Как и запрос, ответ может быть одним из семи типов данных, перечисленных в разделе Типы Данных.

Отправляем ответ ошибки 

Если вам нужно отправить клиенту сообщение об ошибке, следует использовать следующие:

return $this->xmlrpc->send_error_message('123', 'Запрашиваемые сведения отсутствуют');

Первый параметр - номер ошибки, в то время как второй параметр - сообщение об ошибке.

Создание своих Клиента (Client) и Сервера (Server) 

Чтобы помочь вам понять все, что мы рассмотрели до сих пор, давайте создадим пару контроллеров, которые действуют как XML-RPC Клиент и Сервер. Вы будете использовать клиент для отправки запроса на сервер и получите ответ.

Клиент (Client) 

Используя текстовый редактор, создайте контроллер c названием Xmlrpc_client.php. Поместите в него этот код и сохраните этот файл в application/controllers/ каталоге:

<?php

class Xmlrpc_client extends CI_Controller {

        public function index()
        {
                $this->load->helper('url');
                $server_url = site_url('xmlrpc_server');

                $this->load->library('xmlrpc');

                $this->xmlrpc->server($server_url, 80);
                $this->xmlrpc->method('Greetings');

                $request = array('How is it going?');
                $this->xmlrpc->request($request);

                if ( ! $this->xmlrpc->send_request())
                {
                        echo $this->xmlrpc->display_error();
                }
                else
                {
                        echo '<pre>';
                        print_r($this->xmlrpc->display_response());
                        echo '</pre>';
                }
        }
}
?>

Примечание

В приведенном выше коде мы используем “url хелпер”. Вы можете найти больше информации на странице функции хелперов (помощников).

Сервер (Server) 

Используя текстовый редактор, создайте контроллер c названием Xmlrpc_server.php. Поместите в него этот код и сохраните этот файл в application/controllers/ каталоге:

<?php

class Xmlrpc_server extends CI_Controller {

        public function index()
        {
                $this->load->library('xmlrpc');
                $this->load->library('xmlrpcs');

                $config['functions']['Greetings'] = array('function' => 'Xmlrpc_server.process');

                $this->xmlrpcs->initialize($config);
                $this->xmlrpcs->serve();
        }


        public function process($request)
        {
                $parameters = $request->output_parameters();

                $response = array(
                        array(
                                'you_said'  => $parameters[0],
                                'i_respond' => 'Not bad at all.'
                        ),
                        'struct'
                );

                return $this->xmlrpc->send_response($response);
        }
}

Пробуем! 

Теперь посетите ваш сайт используя URL похожий на этот:

example.com/index.php/xmlrpc_client/

Теперь вы должны увидеть сообщение, которое вы отправили на сервер, и его ответ.

Созданный вами клиент отправляет сообщение (“How’s is going?”) на сервер, в “Greetings” метод. Сервер получает запрос и сопоставляет его с process() методом, где отправляется ответ.

Использование ассоциативных массивов параметром запроса 

Если вы хотите использовать ассоциативный массив в параметрах метода вам нужно будет использовать тип данных struct:

$request = array(
        array(
                // Param 0
                array('name' => 'John'),
                'struct'
        ),
        array(
                // Param 1
                array(
                        'size' => 'large',
                        'shape'=>'round'
                ),
                'struct'
        )
);

$this->xmlrpc->request($request);

Можно получить ассоциативный массив при обработке запроса на сервере.

$parameters = $request->output_parameters();
$name = $parameters[0]['name'];
$size = $parameters[1]['size'];
$shape = $parameters[1]['shape'];

Типы данных 

Согласно XML-RPC spec существует семь типов значений, которые вы можете отправить через XML-RPC:

  • int or i4
  • boolean
  • string
  • double
  • dateTime.iso8601
  • base64
  • struct (содержит массив значений)
  • array (содержит массив значений)

Справка класса 

class CI_Xmlrpc 
initialize([$config = array()]) 
Параметры:
  • $config (массив) – Данные конфигурации
Возвращаемый тип:

пустота

Инициализирует XML-RPC библиотеку. Принимает ассоциативный массив содержащий параметры.

server($url[, $port = 80[, $proxy = FALSE[, $proxy_port = 8080]]]) 
Параметры:
  • $url (строка) – URL XML-RPC сервера
  • $port (число) – Порт сервера
  • $proxy (строка) – Дополнительный прокси-сервер
  • $proxy_port (число) – Прослушиваемый порт прокси-сервера
Возвращаемый тип:

пустота

Устанавливает URL и номер порта сервера куда будет отправлен запрос:

$this->xmlrpc->server('http://www.sometimes.com/pings.php', 80);

Основная HTTP проверка подлинности также поддерживается, просто добавьте её в URL сервера:

$this->xmlrpc->server('http://user:pass@localhost/', 80);
timeout($seconds = 5) 
Параметры:
  • $seconds (число) – Время ожидания в секундах
Возвращаемый тип:

пустота

Устанавливает время ожидания (в секундах), по истечении которого запрос будет отменен:

$this->xmlrpc->timeout(6);
method($function) 
Параметры:
  • $function (строка) – Имя метода
Возвращаемый тип:

пустота

Устанавливает метод, который будет запрошен у XML-RPC сервера:

$this->xmlrpc->method('method');

Где method - имя метода.

request($incoming) 
Параметры:
  • $incoming (массив) – Данные запроса
Возвращаемый тип:

пустота

Принимает массив данных и строит запрос для отправки XML-RPC серверу:

$request = array(array('My Photoblog', 'string'), 'http://www.yoursite.com/photoblog/');
$this->xmlrpc->request($request);
send_request() 
Возвращает:TRUE при удаче, FALSE при неудаче
Возвращаемый тип:булево

Метод отправки запроса. Возвращает логическое значение TRUE или FALSE на основе успеха для неудачи, что позволяет использовать условно.

display_error() 
Возвращает:Строку сообщения об ошибке
Возвращаемый тип:строка

Возвращает сообщение об ошибке в виде строки, если ваш запрос не удалось выполнить по каким то причинам.

echo $this->xmlrpc->display_error();
display_response() 
Возвращает:Ответ
Возвращаемый тип:смешанный

Возвращает ответ от удаленного сервера, как только получен запрос. Ответом обычно является ассоциативный массив.

$this->xmlrpc->display_response();
send_error_message($number, $message) 
Параметры:
  • $number (число) – Номер ошибки
  • $message (строка) – Сообщение ошибки
Возвращает:

XML_RPC_Response экземпляр

Возвращаемый тип:

XML_RPC_Response

Этот способ позволяет отправить сообщение об ошибке от сервера к клиенту. Первый параметр - номер ошибки, а второй параметр - сообщение об ошибке.

return $this->xmlrpc->send_error_message(123, 'Запрашиваемые сведения отсутствуют');