XML-RPC в Ruby
Как известно, XML-RPC является достаточно распространенным методом вызова удаленных процедур, основанным на XML. Однако, несмотря на то, что он значительно проще, чем, например, SOAP, его использование все еще иногда достаточно сложно: необходимо сериализовать объекты в специальное XML-представление, затем распарсить полученный релзультат.
Однако, на самом деле, не все так плохо!
В стандартной библиотеке Ruby существует замечательная поддержка XML-RPC, о которой я немного расскажу далее.
Для создания простейшего клиента необходимо всего лишь подключить файл xmlrpc/client, создать объект клиента и вызывать функции RPC, как методы этого объекта. А возвращаемым значением метода является хэш выходных параметров.
require 'xmlrpc/client'
require 'pp'
client = XMLRPC::Client.new2("http://xmlrpc-c.sourceforge.net/api/sample.php")
result = client.call("sample.sumAndDifference", 5, 3)
pp result
Это пример с сайта официальной документации. По идее, result должен представлять из себя хэш, в котором будут содержаться возвращаемые значения. Однако, этот пример не работает (как минимум у меня). При вызове он выдает исключение:
/usr/lib/ruby/1.8/xmlrpc/client.rb:555:in `do_rpc': Wrong content-type (received 'text/html' but expected 'text/xml'): (RuntimeError)
Что же не так? Сервер, к которому обращается клиент почему-то возвращает в заголовке Content-Type значение text/html, хотя ожидается text/xml. Вообще говоря, это стоит считать багом настройки сервера, но если Вы осуществляете запросы к каким-то внешним сервисам, есть вероятность, что какой-то из них так же будет отсылать некорректный Content-Type.
Первое что мне пришло в голову - это отключить проверку в клиенте. Самый простой способ не требует никакой модификации кода библиотеки. Для этого перед использованием клиента необходимо поместить следующий код:
XMLRPC::Client.class_eval do
def parse_content_type(a)
['text/xml']
end
end
То есть мы просто подменяем метод parse_content_type с тем, чтобы он всегда возвращал text/xml. Теперь можно спокойно делать запросы к различным сервисам и вышеприведенный пример выведет что-то вроде:
{"sum"=>8, "difference"=>2}
Теперь можно использовать библиотеку для работы сразличными XML-RPC сервисами в сети.
