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.

Table 16-1. Supported data types

XML-RPC data type

Description

Ruby equivalent

int

Four-byte signed integer

Fixnum or Bignum

boolean

0 (false) or 1 (true)

TrueClass or FalseClass

string

Text or encoded binary data; only the characters < and & are disallowed and rendered as HTML entities

String

double

Double-precision signed floating point number

Float

dateTime.iso8601

Date/time in the format YYYYMMDDTHH:MM:SS (where T is a literal)

XMLRPC::DateTime

base64

base64-encoded binary data

String

struct

An unordered set of key value pairs where the name is always a String and the value can be any XML-RPC data type, including netsted a nested struct or array

Hash

array

A series of values that may be of any of XML-RPC data type, including a netsted struct or array; multiple data types can be used in the context of a single array

Array


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


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net