Стоит задача, поднять web-сервис на защищенном (HTTPS) канале.
Технологий web-сервисов в принципе две: SOAP и XML-RPC. SOAP - тяжелая и замороченная, предназначена для крупных проектов, пока еще не окончательно стандартизована. XML-RPC легкая и полностью стандартизована, построена на использовании XML формата передачи данных между клиентом и сервером по HTTP протоколу. PHP5 поддерживает обе технологии. В дерево исходников PHP5 входит одна из реализаций библиотеки XML-RPC, написанной на С. Правда документация крайне скудная, но разобраться можно.
XML-RPC server:
1. Определяем функции, которые будут доступны клиенту. Для примера напишем функцию сложения двух чисел:
function srvAdd($MethodName, $Params, $AppData)
{
return $Params[0]+$Params[1];
}
Любая функция, регистрируемая на xml-rpc сервере, должна принимать 3 параметра:
$MethodName - внешнее имя функции;
$Params - массив параметров, передаваемых клиентом;
$AppData - дополнительные параметры, передаваемые при вызове функции xmlrpc_server_call_method().
2. Создаем XML-RPC сервер вызовом функции
srv=xmlrpc_server_create();
3. Регистрируем на сервере, определенные ранее функции
xmlrpc_server_register_method($srv, "Add", "srvAdd");
Здесь:
Add - внешнее имя функции srvAdd,
srv - handler сервера.
4. Получаем "сырой" запрос от клиента
$xmlRequest = $HTTP_RAW_POST_DATA;
5. Передаем запрос в диспетчер функций, который автоматически определит какую функцию вызвать.
$response = xmlrpc_server_call_method($srv, $xmlRequest, Null);
Здесь:
$srv - handler xml-rpc сервера;
$xmlRequest - данные от клиента в xml-формате;
Третий параметр, в данном случае пустой, передает дополнительные данные для определенных ранее функций (параметр $AppData).
6. Отдаем клиенту результаты работы функции
print $response;
7. Закрываем сервер.
xmlrpc_server_destroy($srv);
Приведу весь код xml-rpc сервера в котором клиенту доступны несколько функций:
function About($MethodName, $Params, $AppData)
{
$sAbout="ekXMLRPCServer Class v0.9.5\n (c) 2008 Klek\n Author: Eugene Klepikov\n Email: ";
return $sAbout;;
}
//-----------------------------------------------------------------------------
class ekXMLRPCServer
{
private $srvh=null;
private $xmlRequest="";
private $response="";
private $about="";
private $help="";
private $userData=null;
private $arOutOptions=array(
"output_type" => "xml",
"verbosity" => "pretty",
"escaping" => array("markup", "non-ascii", "non-print"),
"version" => "xmlrpc",
"encoding" => "iso-8859-1"
//"encoding" => "utf-8"
);
//-----------------------------------------------------------------------------
function __construct()
{
$this->srvh=xmlrpc_server_create();
$this->registerMethod("system.about", "About");
$this->registerMethod("help", "help");
}
//-----------------------------------------------------------------------------
function __destruct()
{
xmlrpc_server_destroy($this->srvh);
}
//-----------------------------------------------------------------------------
function registerMethod($methodName, $functionName)
{
xmlrpc_server_register_method($this->srvh, $methodName, $functionName);
}
//-----------------------------------------------------------------------------
function request($Request)
{
$this->xmlRequest=$Request;
}
//-----------------------------------------------------------------------------
function run()
{
$this->response=xmlrpc_server_call_method($this->srvh, $this->xmlRequest, $this->userData, $this->arOutOptions);
print $this->response;
}
//-----------------------------------------------------------------------------
}
Поместим файл с кодом xml-rpc сервера в защищенный каталог apache, чтобы к нему можно было коннесктится через SSL https://www.mydomain.ru/xmlrpcserver.php
XML-RPC Client
Клиента проще всего написать на Python, т.к. все нужные библиотеки уже есть в стандартной поставке.
>>> import xmlrpclib
>>> server = xmlrpclib.Server("https://www.mydomain.ru/xmlrpcserver.php")
Теперь можно вызывать функции сервера.
>>> server.Add('10', '15')
>>> 25
>>>
Функции Array() и Dict() различаются типом возвращаемого массива.
>>> server.Array("Peter")
>>>['Peter', 'Hello, Peter. How are you today?']
Array() возвращает список.
>>> server.Dict("Peter")
>>>{'name': 'Peter', 'greeting': 'Hello, Peter. How are you today?'}
Dict() возвращает словарь, т.к. в реализации функции мы использовали именованный массив.
XML-RPC сервер имеет и несколько встроенных функций, одна из которых
>>>server.system.listMethods()
>>>['system.listMethods', 'system.methodHelp', 'system.methodSignature', 'system.describeMethods', 'system.multiCall', 'system.getCapabilities', 'Uptime', 'Array', 'Dict', 'Add']
возвращает список всех доступных на сервере функций.
Замечания:
1. В питоновских библиотеках xmlrpclib, urllib, httplib не предусмотрена проверка сертификата сервера.
2. Для работы с библиотекой XML-RPC в PHP5 нужно поставить модуль php5-xmlrpc из репозитария дистрибутива или, при самостоятельной сборке, добавить к команде configure параметр --with-xmlrpc[=DIR].