Writing an XML-RPC Client
Credit: John-Mason Shackelford
Problem
You want to call a remote method through the XML-RPC web service protocol.
Solution
Use Michael Neumanns xmlrpc4r library, found in Rubys standard library.
Heres the canonical simple XML-RPC example. Given a number, it looks up the name of a U.S. state in an alphabetic list:
require xmlrpc/client server = XMLRPC::Client.new2(http://betty.userland.com/RPC2) server.call(examples.getStateName, 5) # => "California"
Discussion
XML-RPC is a language-independent solution for distributed systems that makes a simple alternative to SOAP (in fact, XML-RPC is an ancestor of SOAP). Although its losing ground to SOAP and REST-style web services, XML-RPC is still used by many blogging engines and popular web services, due to its simplicity and relatively long history.
A XML-RPC request is sent to the server as a specially-formatted HTTP POST request, and the XML-RPC response is encoded in the HTTP response to that request. Since most firewalls allow HTTP traffic, this has the advantage (and disadvantage) that XML-RPC requests work through most firewalls. Since XML-RPC requests are POST requests, typical HTTP caching solutions (which only cache GETs) can be used to speed up XML-RPC requests or save bandwidth.
An XML-RPC request consists of a standard set of HTTP headers, a simple XML document that encodes the name of a remote method to call, and the parameters to pass to that method. The xmlrpc4r library automatically converts between most XML-RPC data types and the corresponding Ruby data types, so you can treat XML-RPC calls almost like local method calls. The main exceptions are date and time objects. You can pass a Ruby Date or Time object into an XML-RPC method that expects a dateTime.iso8601 parameter, but a method that returns a date will always be represented as an instance of XMLRPC::DateTime.
Table 16-1 lists the supported data types of the request parameters and the response.
Note that nil is not a supported XML-RPC value, although some XML-RPC implementations (including xmlrpc4r) follow an extension that allows it.
An XML-RPC response is another XML document, which encodes the return value of the remote method (if you e lucky) or a "fault" (if you e not). xmlrpc4r parses this document and transforms it into the corresponding Ruby objects.
If the remote method returned a fault, xmlrpc4r raises an XMLRPC::FaultException. A fault contains an integer value (the fault code) and a string containing an error message. Heres an example:
begin server.call( oSuchMethod) rescue XMLRPC::FaultException => e puts "Error: fault code #{e.faultCode}" puts e.faultString end # Error: fault code 7 # Can evaluate the expression because the name "noSuchMethod" hasn been defined.
Heres a more interesting XML-RPC example that searches an online UPC database:
def lookup_upc(upc) server = XMLRPC:: Client.new2(http://www.upcdatabase.com/rpc) begin response = server.call(lookupUPC, upc) return response[found] ? response : nil rescue XMLRPC::FaultException => e puts "Error: " puts e.faultCode puts e.faultString end end product = lookup_upc( 18787765654) product[description] # => "Dr Bronners Peppermint Oil Soap" product[size] # => "128 fl oz" lookup_upc( o such UPC) # => nil
See Also
- Michael Neumanns xmlrpc4rHOWTO (http://www.ntecs.de/projects/xmlrpc4r/howto.html)
- The XML-RPC Specification (http://www.xmlrpc.com/spec)
- The extension to XML-RPC that lets it represent nil values (http://ontosys.com/xml-rpc/extensions.php)
- The Ruby Developers Guide, published by Syngress and edited by Michael Neumann, contains over 20 pages devoted to implementing XML-RPC clients and servers with xmlrpc4r.
- Recipe 15.8, "Creating a Login System," shows how to serve XML-RPC requests from within a Rails application
Категории