mirror of https://github.com/tLDP/LDP
1579 lines
53 KiB
XML
1579 lines
53 KiB
XML
<?xml version="1.0"?>
|
|
|
|
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
|
|
|
<!ENTITY license "
|
|
<para>Permission is granted to copy, distribute and/or modify this
|
|
document under the terms of the <ulink type='http'
|
|
url='http://www.fsf.org/copyleft/fdl.html'><citetitle>GNU Free
|
|
Documentation License</citetitle></ulink>, Version 1.1 or any later
|
|
version published by the Free Software Foundation with no Invariant
|
|
Sections, no Front-Cover Texts, and no Back-Cover Texts. You may
|
|
obtain a copy of the <citetitle>GNU Free Documentation
|
|
License</citetitle> from the Free Software Foundation by visiting
|
|
<ulink type='http' url='http://www.fsf.org/'>their Web site</ulink>
|
|
or by writing to: Free Software Foundation, Inc., 59 Temple Place -
|
|
Suite 330, Boston, MA 02111-1307, USA.</para>
|
|
|
|
<para>This manual contains short example programs (<quote>the
|
|
Software</quote>). Permission is hereby granted, free of charge, to
|
|
any person obtaining a copy of the Software, to deal in the Software
|
|
without restriction, including without limitation the rights to use,
|
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following condition:</para>
|
|
|
|
<para>THE SOFTWARE IS PROVIDED <quote>AS IS</quote>, WITHOUT WARRANTY
|
|
OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</para>
|
|
">
|
|
|
|
<!ENTITY % GoodStyleSheets "IGNORE">
|
|
<!--
|
|
<![%GoodStyleSheets;[
|
|
<!ENTITY legal.notice "
|
|
<legalnotice id='xmlrpc-howto-legal'>&license;</legalnotice>
|
|
">
|
|
<!ENTITY legal.section "">
|
|
]]>
|
|
-->
|
|
|
|
<!ENTITY legal.notice "">
|
|
<!ENTITY legal.section "
|
|
<section id='xmlrpc-howto-legal'>
|
|
<title>Legal Notice</title>
|
|
&license;
|
|
</section>
|
|
">
|
|
|
|
]>
|
|
|
|
<article id="xmlrpc-howto">
|
|
<title>XML-RPC HOWTO</title>
|
|
|
|
<articleinfo>
|
|
<title>XML-RPC HOWTO</title>
|
|
|
|
<pubdate>0.8.0, 2001-04-12</pubdate>
|
|
|
|
<editor>
|
|
<firstname>Eric</firstname>
|
|
<surname>Kidd</surname>
|
|
</editor>
|
|
|
|
<authorgroup>
|
|
<author>
|
|
<firstname>Eric</firstname>
|
|
<surname>Kidd</surname>
|
|
<affiliation>
|
|
<orgname>Source Builders</orgname>
|
|
<address><email>eric.kidd@pobox.com</email></address>
|
|
</affiliation>
|
|
</author>
|
|
|
|
<author>
|
|
<firstname>Charles</firstname>
|
|
<surname>Cook</surname>
|
|
<affiliation>
|
|
<orgname>Cook Computing</orgname>
|
|
<address><email>charlescook@ukonline.co.uk</email></address>
|
|
</affiliation>
|
|
</author>
|
|
|
|
<author>
|
|
<othername>And Other Contributors</othername>
|
|
</author>
|
|
</authorgroup>
|
|
|
|
<copyright>
|
|
<year>2001</year>
|
|
<holder>Eric Kidd</holder>
|
|
<holder>Charles Cook</holder>
|
|
</copyright>
|
|
|
|
<abstract>
|
|
<para>Describes how to use XML-RPC to implement clients and servers
|
|
in a variety of languages. Provides example code in Perl, Python, C,
|
|
C++, Java, PHP, XML-RPC.Net and other languages. Includes sections on
|
|
Zope and KDE 2.0. Applies to all operating systems with XML-RPC
|
|
support.</para>
|
|
</abstract>
|
|
|
|
&legal.notice;
|
|
|
|
<revhistory id="revhistory">
|
|
<revision>
|
|
<revnumber>0.9.0</revnumber>
|
|
<date>2001-05-13</date>
|
|
<revremark>Merged in Charles Cook's chapter on
|
|
XML-RPC.Net.</revremark>
|
|
</revision>
|
|
<revision>
|
|
<revnumber>0.8.0</revnumber>
|
|
<date>2001-04-12</date>
|
|
<revremark>Updated section on common interfaces. Added pointer to
|
|
XML-RPC.Net information.</revremark>
|
|
</revision>
|
|
<revision>
|
|
<revnumber>0.7.0</revnumber>
|
|
<date>2001-04-03</date>
|
|
<revremark>Added section on C++ proxy classes.</revremark>
|
|
</revision>
|
|
<revision>
|
|
<revnumber>0.6.0</revnumber>
|
|
<date>2001-02-02</date>
|
|
<revremark>Added sections on Ruby, K and common
|
|
interfaces.</revremark>
|
|
</revision>
|
|
<revision>
|
|
<revnumber>0.5.0</revnumber>
|
|
<date>2001-01-23</date>
|
|
<revremark>Initial version.</revremark>
|
|
</revision>
|
|
</revhistory>
|
|
</articleinfo>
|
|
|
|
&legal.section;
|
|
|
|
<section id="xmlrpc-howto-intro">
|
|
<title>What is XML-RPC?</title>
|
|
|
|
<para><ulink url="http://www.xmlrpc.com/">XML-RPC</ulink> is a simple,
|
|
portable way to make remote procedure calls over HTTP. It can be used
|
|
with Perl, Java, Python, C, C++, PHP and many other programming
|
|
languages. Implementations are available for Unix, Windows and the
|
|
Macintosh.</para>
|
|
|
|
<para>Here's a short XML-RPC client written in Perl. (We use Ken
|
|
MacLeod's <ulink
|
|
url="http://bitsko.slc.ut.us/~ken/xml-rpc/">Frontier::Client</ulink>
|
|
module.)</para>
|
|
|
|
<programlisting format="linespecific">use Frontier::Client;
|
|
$server = Frontier::Client->new(url => 'http://betty.userland.com/RPC2');
|
|
$name = $server->call('examples.getStateName', 41);
|
|
print "$name\n";</programlisting>
|
|
|
|
<para>When run, this program will connect to the remote server, get the
|
|
state name, and print it. (State #41 should be South Dakota in this
|
|
example.)</para>
|
|
|
|
<para>Here's the same program in Python. (This time, we use Fredrik
|
|
Lundh's <ulink
|
|
url="http://www.pythonware.com/products/xmlrpc/">xmlrpclib</ulink>.)</para>
|
|
|
|
<programlisting format="linespecific">python> import xmlrpclib
|
|
python> server = xmlrpclib.Server("http://betty.userland.com/RPC2")
|
|
python> server.examples.getStateName(41)
|
|
'South Dakota'</programlisting>
|
|
|
|
<para>In the following chapters, you'll learn how to write XML-RPC
|
|
clients and servers in a variety of programming languages.</para>
|
|
|
|
<section id="xmlrpc-howto-spec">
|
|
<title>How it Works</title>
|
|
|
|
<para>XML-RPC is described fully in Dave Winer's <ulink
|
|
url="http://www.xmlrpc.com/spec">official specification</ulink>. If
|
|
you're curious, go ahead and take a look—it's a quick and
|
|
straight-forward read.</para>
|
|
|
|
<para>On the wire, XML-RPC values are encoded as XML:</para>
|
|
|
|
<programlisting><methodCall>
|
|
<methodName>sample.sumAndDifference</methodName>
|
|
<params>
|
|
<param><value><int>5</int></value></param>
|
|
<param><value><int>3</int></value></param>
|
|
</params>
|
|
</methodCall></programlisting>
|
|
|
|
<para>This is verbose, but compresses readily. It's also faster than
|
|
you might expect—according to measurements by Rick Blair, a
|
|
round-trip XML-RPC call takes 3 milliseconds using Hannes
|
|
Wallnöfer's Java implementation.</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-types">
|
|
<title>Supported Data Types</title>
|
|
|
|
<para>XML-RPC supports the following data types:</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>int</literal></term>
|
|
<listitem>
|
|
<para>A signed, 32-bit integer.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>string</literal></term>
|
|
<listitem>
|
|
<para>An ASCII string, which may contain NULL bytes. (Actually,
|
|
several XML-RPC implementations support Unicode, thanks to the
|
|
underlying features of XML.)</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>boolean</literal></term>
|
|
<listitem>
|
|
<para>Either true or false.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>double</literal></term>
|
|
<listitem>
|
|
<para>A double-precision floating point number. (Accuracy may
|
|
be limited in some implementations.)</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>dateTime.iso8601</literal></term>
|
|
<listitem>
|
|
<para>A date and time. Unfortunately, since XML-RPC forbids the
|
|
use of timezones, this is very nearly useless.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>base64</literal></term>
|
|
<listitem>
|
|
<para>Raw binary data of any length; encoded using Base64 on
|
|
the wire. Very useful. (Some implementations don't like to
|
|
receive zero bytes of data, though.)</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>array</literal></term>
|
|
<listitem>
|
|
<para>An one-dimensional array of values. Individual values may
|
|
be of any type.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><literal>struct</literal></term>
|
|
<listitem>
|
|
<para>A collection of key-value pairs. The keys are strings;
|
|
the values may be of any type.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-history">
|
|
<title>The History of XML-RPC</title>
|
|
|
|
<para>XML-RPC was inspired by two earlier protocols. The first is an
|
|
anonymous RPC protocol designed by Dave Winer and announced in an
|
|
<ulink
|
|
url="http://davenet.userland.com/1998/02/27/rpcOverHttpViaXml">old
|
|
DaveNet essay</ulink>. (This is why XML-RPC servers are often
|
|
installed under <filename>/RPC2</filename>.) The other, more
|
|
important inspiration was an early draft of the SOAP protocol.</para>
|
|
|
|
<para>A longer <ulink
|
|
url="http://www.xmlrpc.com/stories/storyReader$555">history of
|
|
XML-RPC</ulink> has been generously provided by Dave Winer. This also
|
|
explains the relationship between XML-RPC and SOAP.</para>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-competition">
|
|
<title>XML-RPC vs. Other Protocols</title>
|
|
|
|
<para>XML-RPC is not the only way to make remote procedure calls. Other
|
|
popular protocols include CORBA, DCOM and SOAP. Each of these protocols
|
|
has advantages and disadvantages.</para>
|
|
|
|
<para>The opinions in the section are obviously biased; please take
|
|
them with a grain of salt.</para>
|
|
|
|
<section id="xmlrpc-howto-corba">
|
|
<title>XML-RPC vs. CORBA</title>
|
|
|
|
<para><ulink url="http://www.corba.org/">CORBA</ulink> is a popular
|
|
protocol for writing distributed, object-oriented applications. It's
|
|
typically used in multi-tier enterprise applications. Recently, it's
|
|
also been adopted by the <ulink
|
|
url="http://www.gnome.org/">Gnome</ulink> project for
|
|
interapplication communication.</para>
|
|
|
|
<para>CORBA is well-supported by many vendors and several free
|
|
software projects. CORBA works well with Java and C++, and is
|
|
available for many other languages. CORBA also provides an excellent
|
|
<glossterm>interface definition language</glossterm> (IDL), allowing
|
|
you to define readable, object-oriented APIs.</para>
|
|
|
|
<para>Unfortunately, CORBA is very complex. It has a steep
|
|
learning curve, requires significant effort to implement, and
|
|
requires fairly sophisticated clients. It's better-suited to
|
|
enterprise and desktop applications than it is to distributed web
|
|
applications.</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-dcom">
|
|
<title>XML-RPC vs. DCOM</title>
|
|
|
|
<para><ulink
|
|
url="http://www.microsoft.com/com/tech/DCOM.asp">DCOM</ulink> is
|
|
Microsoft's answer to CORBA. It's great if you're already using COM
|
|
components, and you don't need to talk to non-Microsoft
|
|
systems. Otherwise, it won't help you very much.</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-soap">
|
|
<title>XML-RPC vs. SOAP</title>
|
|
|
|
<para><ulink url="http://www.w3.org/TR/SOAP/">SOAP</ulink> is very
|
|
similar to XML-RPC. It, too, works by marshaling procedure calls
|
|
over HTTP as XML documents. Unfortunately, SOAP appears to be
|
|
suffering from specification creep.</para>
|
|
|
|
<para>SOAP was originally created as a collaboration between
|
|
UserLand, DevelopMentor and Microsoft. The initial public release was
|
|
basically XML-RPC with namespaces and longer element names. Since
|
|
then, however, SOAP has been turned over a W3C working group.</para>
|
|
|
|
<para>Unfortunately, the working group has been adding a laundry-list
|
|
of strange features to SOAP. As of the current writing, SOAP supports
|
|
XML Schemas, enumerations, strange hybrids of structs and arrays, and
|
|
custom types. At the same time, several aspects of SOAP are
|
|
implementation defined.</para>
|
|
|
|
<para>Basically, if you like XML-RPC, but wish the protocol had more
|
|
features, check out SOAP. :-)</para>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-interfaces">
|
|
<title>Common XML-RPC Interfaces</title>
|
|
|
|
<para>Several XML-RPC servers provide built-in methods. These aren't
|
|
part of XML-RPC itself, but they make handy add-ons.</para>
|
|
|
|
<section id="xmlrpc-howto-api-introspection">
|
|
<title>Introspection: Discovering Server APIs</title>
|
|
|
|
<para>Edd Dumbill <ulink
|
|
url="http://xmlrpc.usefulinc.com/doc/reserved.html">proposed</ulink>
|
|
the following set of methods:</para>
|
|
|
|
<synopsis><returnvalue>array</returnvalue> <function>system.listMethods</function> ()
|
|
<returnvalue>string</returnvalue> <function>system.methodHelp</function> (<type>string</type> <parameter>methodName</parameter>)
|
|
<returnvalue>array</returnvalue> <function>system.methodSignature</function> (<type>string</type> <parameter>methodName</parameter>)</synopsis>
|
|
|
|
<para>If a server supports these methods, you can ask it to print out
|
|
some documentation:</para>
|
|
|
|
<programlisting>import xmlrpclib
|
|
server = xmlrpclib.Server("http://xmlrpc-c.sourceforge.net/api/sample.php")
|
|
for method in server.system.listMethods():
|
|
print method
|
|
print server.system.methodHelp(method)
|
|
print</programlisting>
|
|
|
|
<para>These methods are currently supported by servers written in
|
|
PHP, C and Microsoft .NET. Partial introspection support is included
|
|
in recent updates to UserLand Frontier. Introspection support for
|
|
Perl, Python and Java is available at the <ulink
|
|
url="http://xmlrpc-c.sourceforge.net/hacks.php">XML-RPC
|
|
Hacks</ulink> page. Please feel free to add introspection support to
|
|
other XML-RPC servers!</para>
|
|
|
|
<para>Various client-side tools (documentation generators, wrapper
|
|
generators, and so on) can be found at the XML-RPC Hacks page as
|
|
well.</para>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-api-boxcarring">
|
|
<title>Boxcarring: Sending Multiple Requests at Once</title>
|
|
|
|
<para>If you're writing an XML-RPC client which makes lots of small
|
|
function calls, you may discover that your round-trip time is fairly
|
|
high, thanks to Internet backbone latency. Some servers allow you to
|
|
batch up multiple requests using the following function:</para>
|
|
|
|
<synopsis><returnvalue>array</returnvalue> <function>system.multicall</function> (<type>array</type> <parameter>calls</parameter>)</synopsis>
|
|
|
|
<para>You can find more information in the <ulink
|
|
url="http://www.xmlrpc.com/discuss/msgReader$1208">system.multicall
|
|
RFC</ulink>.</para>
|
|
|
|
<para>This method is currently supported by servers written in C and
|
|
UserLand Frontier. Servers written in Python and Perl can use the
|
|
code at the <ulink
|
|
url="http://xmlrpc-c.sourceforge.net/hacks.php">XML-RPC
|
|
Hacks</ulink> page.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-api">
|
|
<title>A Sample API: <function>sumAndDifference</function></title>
|
|
|
|
<para>To demonstrate XML-RPC, we implement the following API in as many
|
|
languages as possible.</para>
|
|
|
|
<synopsis><returnvalue>struct</returnvalue> <function>sample.sumAndDifference</function> (<type>int</type> <parameter>x</parameter>, <type>int</type> <parameter>y</parameter>)</synopsis>
|
|
|
|
<para>This function takes two integers as arguments, and returns an
|
|
XML-RPC <literal><struct></literal> containing two elements:</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><parameter>sum</parameter></term>
|
|
<listitem>
|
|
<para>The sum of the two integers.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><parameter>difference</parameter></term>
|
|
<listitem>
|
|
<para>The difference between the two integers.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<para>It's not very useful, but it makes a nice example. :-)</para>
|
|
|
|
<para>This function (and others) are available using the URL
|
|
<literal>http://xmlrpc-c.sourceforge.net/api/sample.php</literal>.
|
|
(This URL won't do anything in a browser; it requires an XML-RPC
|
|
client.)</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-perl">
|
|
<title>Using XML-RPC with Perl</title>
|
|
|
|
<para>Ken MacLeod has implemented XML-RPC for Perl. You can find his
|
|
Frontier::RPC module at his <ulink
|
|
url="http://bitsko.slc.ut.us/~ken/xml-rpc/">website</ulink> or through
|
|
<ulink url="http://www.cpan.org/">CPAN</ulink>.</para>
|
|
|
|
<para>To install Frontier::RPC, download the package and compile
|
|
it in the standard fashion:</para>
|
|
|
|
<programlisting>bash$ gunzip -c Frontier-RPC-0.07b1.tar.gz | tar xvf -
|
|
bash$ cd Frontier-RPC-0.07b1
|
|
bash$ perl Makefile.PL
|
|
bash$ make
|
|
bash$ make test
|
|
bash$ su -c 'make install'</programlisting>
|
|
|
|
<para>(The process will be slightly different on Windows systems, or if
|
|
you don't have root access. Consult your Perl documentation for
|
|
details.)</para>
|
|
|
|
<section id="xmlrpc-howto-perl-client">
|
|
<title>A Perl Client</title>
|
|
|
|
<para>The following program shows how to call an XML-RPC server from
|
|
Perl:</para>
|
|
|
|
<programlisting>use Frontier::Client;
|
|
|
|
# Make an object to represent the XML-RPC server.
|
|
$server_url = 'http://xmlrpc-c.sourceforge.net/api/sample.php';
|
|
$server = Frontier::Client->new(url => $server_url);
|
|
|
|
# Call the remote server and get our result.
|
|
$result = $server->call('sample.sumAndDifference', 5, 3);
|
|
$sum = $result->{'sum'};
|
|
$difference = $result->{'difference'};
|
|
|
|
print "Sum: $sum, Difference: $difference\n";</programlisting>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-perl-server">
|
|
<title>A Stand-Alone Perl Server</title>
|
|
|
|
<para>The following program shows how to write an XML-RPC server in
|
|
Perl:</para>
|
|
|
|
<programlisting>use Frontier::Daemon;
|
|
|
|
sub sumAndDifference {
|
|
my ($x, $y) = @_;
|
|
return {'sum' => $x + $y, 'difference' => $x - $y};
|
|
}
|
|
|
|
# Call me as http://localhost:8080/RPC2
|
|
$methods = {'sample.sumAndDifference' => \&sumAndDifference};
|
|
Frontier::Daemon->new(LocalPort => 8080, methods => $methods)
|
|
or die "Couldn't start HTTP server: $!";</programlisting>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-perl-cgi">
|
|
<title>A CGI-Based Perl Server</title>
|
|
|
|
<para><literal>Frontier::RPC2</literal> doesn't provide built-in
|
|
support for CGI-based servers. It <emphasis>does</emphasis>, however,
|
|
provide most of the pieces you'll need.</para>
|
|
|
|
<para>Save the following code as
|
|
<filename>sumAndDifference.cgi</filename> in your web server's
|
|
<filename>cgi-bin</filename> directory. (On Unix systems, you'll need
|
|
to make it executable by typing <literal>chmod +x
|
|
sumAndDifference.cgi</literal>.)</para>
|
|
|
|
<programlisting>#!/usr/bin/perl -w
|
|
|
|
use strict;
|
|
use Frontier::RPC2;
|
|
|
|
sub sumAndDifference {
|
|
my ($x, $y) = @_;
|
|
return {'sum' => $x + $y, 'difference' => $x - $y};
|
|
}
|
|
|
|
process_cgi_call({'sample.sumAndDifference' => \&sumAndDifference});
|
|
|
|
|
|
#==========================================================================
|
|
# CGI Support
|
|
#==========================================================================
|
|
# Simple CGI support for Frontier::RPC2. You can copy this into your CGI
|
|
# scripts verbatim, or you can package it into a library.
|
|
# (Based on xmlrpc_cgi.c by Eric Kidd <http://xmlrpc-c.sourceforge.net/>.)
|
|
|
|
# Process a CGI call.
|
|
sub process_cgi_call ($) {
|
|
my ($methods) = @_;
|
|
|
|
# Get our CGI request information.
|
|
my $method = $ENV{'REQUEST_METHOD'};
|
|
my $type = $ENV{'CONTENT_TYPE'};
|
|
my $length = $ENV{'CONTENT_LENGTH'};
|
|
|
|
# Perform some sanity checks.
|
|
http_error(405, "Method Not Allowed") unless $method eq "POST";
|
|
http_error(400, "Bad Request") unless $type eq "text/xml";
|
|
http_error(411, "Length Required") unless $length > 0;
|
|
|
|
# Fetch our body.
|
|
my $body;
|
|
my $count = read STDIN, $body, $length;
|
|
http_error(400, "Bad Request") unless $count == $length;
|
|
|
|
# Serve our request.
|
|
my $coder = Frontier::RPC2->new;
|
|
send_xml($coder->serve($body, $methods));
|
|
}
|
|
|
|
# Send an HTTP error and exit.
|
|
sub http_error ($$) {
|
|
my ($code, $message) = @_;
|
|
print <<"EOD";
|
|
Status: $code $message
|
|
Content-type: text/html
|
|
|
|
<title>$code $message</title>
|
|
<h1>$code $message</h1>
|
|
<p>Unexpected error processing XML-RPC request.</p>
|
|
EOD
|
|
exit 0;
|
|
}
|
|
|
|
# Send an XML document (but don't exit).
|
|
sub send_xml ($) {
|
|
my ($xml_string) = @_;
|
|
my $length = length($xml_string);
|
|
print <<"EOD";
|
|
Status: 200 OK
|
|
Content-type: text/xml
|
|
Content-length: $length
|
|
|
|
EOD
|
|
# We want precise control over whitespace here.
|
|
print $xml_string;
|
|
}</programlisting>
|
|
|
|
<para>You can copy the utility routines into your own CGI
|
|
scripts.</para>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-python">
|
|
<title>Using XML-RPC with Python</title>
|
|
|
|
<para>Fredrik Lundh has provided an excellent <ulink
|
|
url="http://www.pythonware.com/products/xmlrpc/">XML-RPC library for
|
|
Python</ulink>.</para>
|
|
|
|
<para>To install, download the latest version. You can either stick the
|
|
<filename>*.py</filename> files in the same directory as your Python
|
|
code, or you can install them in your system's Python directory.</para>
|
|
|
|
<para>RedHat 6.2 users can type the following:</para>
|
|
|
|
<programlisting>bash$ mkdir xmlrpclib-0.9.8
|
|
bash$ cd xmlrpclib-0.9.8
|
|
bash$ unzip ../xmlrpc-0.9.8-990621.zip
|
|
bash$ python
|
|
python> import xmlrpclib
|
|
python> import xmlrpcserver
|
|
python> <keycap>Control-D</keycap>
|
|
bash$ su -c 'cp *.py *.pyc /usr/lib/python1.5/'</programlisting>
|
|
|
|
<para>We <literal>import</literal> two of the <filename>*.py</filename>
|
|
files to trick Python into compiling them. Users of other platforms
|
|
should consult their Python documentation.</para>
|
|
|
|
<para>For more Python examples, see the article <ulink
|
|
url="http://www.oreillynet.com/pub/a/python/2001/01/17/xmlrpcserver.html">XML-RPC:
|
|
It Works Both Ways</ulink> on the O'Reilly Network.</para>
|
|
|
|
<section id="xmlrpc-howto-python-client">
|
|
<title>A Python Client</title>
|
|
|
|
<para>The following program shows how to call an XML-RPC server from
|
|
Python:</para>
|
|
|
|
<programlisting>import xmlrpclib
|
|
|
|
# Create an object to represent our server.
|
|
server_url = 'http://xmlrpc-c.sourceforge.net/api/sample.php';
|
|
server = xmlrpclib.Server(server_url);
|
|
|
|
# Call the server and get our result.
|
|
result = server.sample.sumAndDifference(5, 3)
|
|
print "Sum:", result['sum']
|
|
print "Difference:", result['difference']</programlisting>
|
|
|
|
</section>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-c">
|
|
<title>Using XML-RPC with C and C++</title>
|
|
|
|
<para>To get a copy of XML-RPC for C/C++, see the <ulink
|
|
url="http://xmlrpc-c.sourceforge.net">xmlrpc-c website</ulink>.</para>
|
|
|
|
<para>You can either download everything in RPM format, or you can
|
|
build it from source.</para>
|
|
|
|
<section id="xmlrpc-howto-c-client">
|
|
<title>A C Client</title>
|
|
|
|
<para>Save the following code in a file called
|
|
<filename>getSumAndDifference.c</filename>:</para>
|
|
|
|
<programlisting>#include <stdio.h>
|
|
#include <xmlrpc.h>
|
|
#include <xmlrpc_client.h>
|
|
|
|
#define NAME "XML-RPC getSumAndDifference C Client"
|
|
#define VERSION "0.1"
|
|
#define SERVER_URL "http://xmlrpc-c.sourceforge.net/api/sample.php"
|
|
|
|
void die_if_fault_occurred (xmlrpc_env *env)
|
|
{
|
|
/* Check our error-handling environment for an XML-RPC fault. */
|
|
if (env->fault_occurred) {
|
|
fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
|
|
env->fault_string, env->fault_code);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
int main (int argc, char** argv)
|
|
{
|
|
xmlrpc_env env;
|
|
xmlrpc_value *result;
|
|
xmlrpc_int32 sum, difference;
|
|
|
|
/* Start up our XML-RPC client library. */
|
|
xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);
|
|
xmlrpc_env_init(&env);
|
|
|
|
/* Call our XML-RPC server. */
|
|
result = xmlrpc_client_call(&env, SERVER_URL,
|
|
"sample.sumAndDifference", "(ii)",
|
|
(xmlrpc_int32) 5,
|
|
(xmlrpc_int32) 3);
|
|
die_if_fault_occurred(&env);
|
|
|
|
/* Parse our result value. */
|
|
xmlrpc_parse_value(&env, result, "{s:i,s:i,*}",
|
|
"sum", &sum,
|
|
"difference", &difference);
|
|
die_if_fault_occurred(&env);
|
|
|
|
/* Print out our sum and difference. */
|
|
printf("Sum: %d, Difference: %d\n", (int) sum, (int) difference);
|
|
|
|
/* Dispose of our result value. */
|
|
xmlrpc_DECREF(result);
|
|
|
|
/* Shutdown our XML-RPC client library. */
|
|
xmlrpc_env_clean(&env);
|
|
xmlrpc_client_cleanup();
|
|
|
|
return 0;
|
|
}</programlisting>
|
|
|
|
<para>To compile it, you can type:</para>
|
|
|
|
<programlisting>bash$ CLIENT_CFLAGS=`xmlrpc-c-config libwww-client --cflags`
|
|
bash$ CLIENT_LIBS=`xmlrpc-c-config libwww-client --libs`
|
|
bash$ gcc $CLIENT_CFLAGS -o getSumAndDifference getSumAndDifference.c $CLIENT_LIBS</programlisting>
|
|
|
|
<para>You may need to replace <command>gcc</command> with the name of
|
|
your system's C compiler.</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-cc-client">
|
|
<title>A C++ Client</title>
|
|
|
|
<para>Save the following code in a file called
|
|
<filename>getSumAndDifference2.cc</filename>:</para>
|
|
|
|
<programlisting>#include <iostream.h>
|
|
#include <XmlRpcCpp.h>
|
|
|
|
#define NAME "XML-RPC getSumAndDifference C++ Client"
|
|
#define VERSION "0.1"
|
|
#define SERVER_URL "http://xmlrpc-c.sourceforge.net/api/sample.php"
|
|
|
|
static void get_sum_and_difference () {
|
|
|
|
// Build our parameter array.
|
|
XmlRpcValue param_array = XmlRpcValue::makeArray();
|
|
param_array.arrayAppendItem(XmlRpcValue::makeInt(5));
|
|
param_array.arrayAppendItem(XmlRpcValue::makeInt(3));
|
|
|
|
// Create an object to resprent the server, and make our call.
|
|
XmlRpcClient server (SERVER_URL);
|
|
XmlRpcValue result = server.call("sample.sumAndDifference", param_array);
|
|
|
|
// Extract the sum and difference from our struct.
|
|
XmlRpcValue::int32 sum = result.structGetValue("sum").getInt();
|
|
XmlRpcValue::int32 diff = result.structGetValue("difference").getInt();
|
|
|
|
cout << "Sum: " << sum << ", Difference: " << diff << endl;
|
|
}
|
|
|
|
int main (int argc, char **argv) {
|
|
|
|
// Start up our client library.
|
|
XmlRpcClient::Initialize(NAME, VERSION);
|
|
|
|
// Call our client routine, and watch out for faults.
|
|
try {
|
|
get_sum_and_difference();
|
|
} catch (XmlRpcFault& fault) {
|
|
cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode()
|
|
<< ": " << fault.getFaultString() << endl;
|
|
XmlRpcClient::Terminate();
|
|
exit(1);
|
|
}
|
|
|
|
// Shut down our client library.
|
|
XmlRpcClient::Terminate();
|
|
return 0;
|
|
}</programlisting>
|
|
|
|
<para>To compile it, you can type:</para>
|
|
|
|
<programlisting>bash$ CLIENT_CFLAGS=`xmlrpc-c-config c++ libwww-client --cflags`
|
|
bash$ CLIENT_LIBS=`xmlrpc-c-config c++ libwww-client --libs`
|
|
bash$ c++ $CLIENT_CFLAGS -o getSumAndDifference2 getSumAndDifference2.cc $CLIENT_LIBS</programlisting>
|
|
|
|
<para>You'll need a reasonably modern C++ compiler for this to
|
|
work.</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-cc-proxy">
|
|
<title>A C++ Client with Proxy Classes</title>
|
|
|
|
<para>If your XML-RPC server supports the <link
|
|
linkend="xmlrpc-howto-api-introspection">Introspection API</link>,
|
|
you can automatically generate C++ proxy classes for it. To generate
|
|
a proxy class, type the following command and save the output to a
|
|
file:</para>
|
|
|
|
<programlisting>bash$ xml-rpc-api2cpp \
|
|
> http://xmlrpc-c.sourceforge.net/api/sample.php sample SampleProxy</programlisting>
|
|
|
|
<para>This will generate a proxy class named
|
|
<literal>SampleProxy</literal> containing wrappers for all the
|
|
methods beginning with <literal>sample</literal>. You can edit this
|
|
class in any fashion you'd like.</para>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-c-cgi">
|
|
<title>A CGI-Based C Server</title>
|
|
|
|
<para>Save the following code in a file called
|
|
<filename>sumAndDifference.c</filename>:</para>
|
|
|
|
<programlisting>#include <xmlrpc.h>
|
|
#include <xmlrpc_cgi.h>
|
|
|
|
xmlrpc_value *
|
|
sumAndDifference (xmlrpc_env *env, xmlrpc_value *param_array, void *user_data)
|
|
{
|
|
xmlrpc_int32 x, y;
|
|
|
|
/* Parse our argument array. */
|
|
xmlrpc_parse_value(env, param_array, "(ii)", &x, &y);
|
|
if (env->fault_occurred)
|
|
return NULL;
|
|
|
|
/* Return our result. */
|
|
return xmlrpc_build_value(env, "{s:i,s:i}",
|
|
"sum", x + y,
|
|
"difference", x - y);
|
|
}
|
|
|
|
int main (int argc, char **argv)
|
|
{
|
|
/* Set up our CGI library. */
|
|
xmlrpc_cgi_init(XMLRPC_CGI_NO_FLAGS);
|
|
|
|
/* Install our only method (with a method signature and a help string). */
|
|
xmlrpc_cgi_add_method_w_doc("sample.sumAndDifference",
|
|
&sumAndDifference, NULL,
|
|
"S:ii", "Add and subtract two integers.");
|
|
|
|
/* Call the appropriate method. */
|
|
xmlrpc_cgi_process_call();
|
|
|
|
/* Clean up our CGI library. */
|
|
xmlrpc_cgi_cleanup();
|
|
}</programlisting>
|
|
|
|
<para>To compile it, you can type:</para>
|
|
|
|
<programlisting>bash$ CGI_CFLAGS=`xmlrpc-c-config cgi-server --cflags`
|
|
bash$ CGI_LIBS=`xmlrpc-c-config cgi-server --libs`
|
|
bash$ gcc $CGI_CFLAGS -o sumAndDifference.cgi sumAndDifference.c $CGI_LIBS</programlisting>
|
|
|
|
<para>Once this is done, copy
|
|
<filename>sumAndDifference.cgi</filename> into your webserver's
|
|
<filename>cgi-bin</filename> directory.</para>
|
|
|
|
</section>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-java">
|
|
<title>Using XML-RPC with Java</title>
|
|
|
|
<para>Hannes Wallnöfer has provided <ulink
|
|
url="http://helma.at/hannes/xmlrpc/">an excellent
|
|
implementation</ulink> of XML-RPC for Java.</para>
|
|
|
|
<para>To install it, download the distribution, unzip it, and add the
|
|
<filename>*.jar</filename> files to your <envar>CLASSPATH</envar>. On a
|
|
Unix system, you can do this by typing:</para>
|
|
|
|
<programlisting>bash$ unzip xmlrpc-java.zip
|
|
bash$ cd xmlrpc-java/lib
|
|
bash$ CLASSPATH=`pwd`/openxml-1.2.jar:`pwd`/xmlrpc.jar:$CLASSPATH</programlisting>
|
|
|
|
<section id="xmlrpc-howto-java-client">
|
|
<title>A Java Client</title>
|
|
|
|
<para>Save the following program in a file named
|
|
<filename>JavaClient.java</filename>.</para>
|
|
|
|
<programlisting>import java.util.Vector;
|
|
import java.util.Hashtable;
|
|
import helma.xmlrpc.*;
|
|
|
|
public class JavaClient {
|
|
|
|
// The location of our server.
|
|
private final static String server_url =
|
|
"http://xmlrpc-c.sourceforge.net/api/sample.php";
|
|
|
|
public static void main (String [] args) {
|
|
try {
|
|
|
|
// Create an object to represent our server.
|
|
XmlRpcClient server = new XmlRpcClient(server_url);
|
|
|
|
// Build our parameter list.
|
|
Vector params = new Vector();
|
|
params.addElement(new Integer(5));
|
|
params.addElement(new Integer(3));
|
|
|
|
// Call the server, and get our result.
|
|
Hashtable result =
|
|
(Hashtable) server.execute("sample.sumAndDifference", params);
|
|
int sum = ((Integer) result.get("sum")).intValue();
|
|
int difference = ((Integer) result.get("difference")).intValue();
|
|
|
|
// Print out our result.
|
|
System.out.println("Sum: " + Integer.toString(sum) +
|
|
", Difference: " +
|
|
Integer.toString(difference));
|
|
|
|
} catch (XmlRpcException exception) {
|
|
System.err.println("JavaClient: XML-RPC Fault #" +
|
|
Integer.toString(exception.code) + ": " +
|
|
exception.toString());
|
|
} catch (Exception exception) {
|
|
System.err.println("JavaClient: " + exception.toString());
|
|
}
|
|
}
|
|
}</programlisting>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-java-server">
|
|
<title>A Stand-Alone Java Server</title>
|
|
|
|
<para>Save the following program in a file named
|
|
<filename>JavaServer.java</filename>.</para>
|
|
|
|
<programlisting>import java.util.Hashtable;
|
|
import helma.xmlrpc.*;
|
|
|
|
public class JavaServer {
|
|
|
|
public JavaServer () {
|
|
// Our handler is a regular Java object. It can have a
|
|
// constructor and member variables in the ordinary fashion.
|
|
// Public methods will be exposed to XML-RPC clients.
|
|
}
|
|
|
|
public Hashtable sumAndDifference (int x, int y) {
|
|
Hashtable result = new Hashtable();
|
|
result.put("sum", new Integer(x + y));
|
|
result.put("difference", new Integer(x - y));
|
|
return result;
|
|
}
|
|
|
|
public static void main (String [] args) {
|
|
try {
|
|
|
|
// Invoke me as <http://localhost:8080/RPC2>.
|
|
WebServer server = new WebServer(8080);
|
|
server.addHandler("sample", new JavaServer());
|
|
|
|
} catch (Exception exception) {
|
|
System.err.println("JavaServer: " + exception.toString());
|
|
}
|
|
}
|
|
}</programlisting>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-php">
|
|
<title>Using XML-RPC with PHP</title>
|
|
|
|
<para>Edd Dumbill has implemented XML-RPC for PHP. You can download it
|
|
from the <ulink url="http://xmlrpc.usefulinc.com/">UsefulInc XML-RPC
|
|
website</ulink>.</para>
|
|
|
|
<para>To install the distribution, decompress it and copy
|
|
<filename>xmlrpc.inc</filename> and <filename>xmlrpcs.inc</filename>
|
|
into the same directory as your PHP scripts.</para>
|
|
|
|
<section id="xmlrpc-howto-php-client">
|
|
<title>A PHP Client</title>
|
|
|
|
<para>The following script shows how to embed XML-RPC calls into a
|
|
web page.</para>
|
|
|
|
<programlisting><html>
|
|
<head>
|
|
<title>XML-RPC PHP Demo</title>
|
|
</head>
|
|
<body>
|
|
<h1>XML-RPC PHP Demo</h1>
|
|
|
|
<?php
|
|
include 'xmlrpc.inc';
|
|
|
|
// Make an object to represent our server.
|
|
$server = new xmlrpc_client('/api/sample.php',
|
|
'xmlrpc-c.sourceforge.net', 80);
|
|
|
|
// Send a message to the server.
|
|
$message = new xmlrpcmsg('sample.sumAndDifference',
|
|
array(new xmlrpcval(5, 'int'),
|
|
new xmlrpcval(3, 'int')));
|
|
$result = $server->send($message);
|
|
|
|
// Process the response.
|
|
if (!$result) {
|
|
print "<p>Could not connect to HTTP server.</p>";
|
|
} elseif ($result->faultCode()) {
|
|
print "<p>XML-RPC Fault #" . $result->faultCode() . ": " .
|
|
$result->faultString();
|
|
} else {
|
|
$struct = $result->value();
|
|
$sumval = $struct->structmem('sum');
|
|
$sum = $sumval->scalarval();
|
|
$differenceval = $struct->structmem('difference');
|
|
$difference = $differenceval->scalarval();
|
|
print "<p>Sum: " . htmlentities($sum) .
|
|
", Difference: " . htmlentities($difference) . "</p>";
|
|
}
|
|
?>
|
|
|
|
</body></html></programlisting>
|
|
|
|
<para>If your webserver doesn't run PHP scripts, see the <ulink
|
|
url="http://www.php.net/">PHP website</ulink> for more
|
|
information.</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-php-server">
|
|
<title>A PHP Server</title>
|
|
|
|
<para>The following script shows how to implement an XML-RPC server
|
|
using PHP.</para>
|
|
|
|
<programlisting><?php
|
|
include 'xmlrpc.inc';
|
|
include 'xmlrpcs.inc';
|
|
|
|
function sumAndDifference ($params) {
|
|
|
|
// Parse our parameters.
|
|
$xval = $params->getParam(0);
|
|
$x = $xval->scalarval();
|
|
$yval = $params->getParam(1);
|
|
$y = $yval->scalarval();
|
|
|
|
// Build our response.
|
|
$struct = array('sum' => new xmlrpcval($x + $y, 'int'),
|
|
'difference' => new xmlrpcval($x - $y, 'int'));
|
|
return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
|
|
}
|
|
|
|
// Declare our signature and provide some documentation.
|
|
// (The PHP server supports remote introspection. Nifty!)
|
|
$sumAndDifference_sig = array(array('struct', 'int', 'int'));
|
|
$sumAndDifference_doc = 'Add and subtract two numbers';
|
|
|
|
new xmlrpc_server(array('sample.sumAndDifference' =>
|
|
array('function' => 'sumAndDifference',
|
|
'signature' => $sumAndDifference_sig,
|
|
'docstring' => $sumAndDifference_doc)));
|
|
?></programlisting>
|
|
|
|
<para>You would normally invoke this as something like
|
|
<literal>http://localhost/path/sumAndDifference.php</literal>.</para>
|
|
|
|
</section>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-dotnet">
|
|
<title>Using XML-RPC with Microsoft .NET</title>
|
|
|
|
<para><emphasis>(This section of the XML-RPC HOWTO was generously
|
|
provided by Charles Cook.)</emphasis></para>
|
|
|
|
<para>Charles Cook has implemented XML-RPC for Microsoft's .NET
|
|
environment. You can find his XML-RPC.Net library at <ulink
|
|
url="http://www.cookcomputing.com/xmlrpc/xmlrpc.shtml">the Cook
|
|
Computing website</ulink>.</para>
|
|
|
|
<para>The following code requires the .NET SDK to be installed. To
|
|
build and run XML-RPC.Net client and server applications, unzip
|
|
<filename>cookcomputing.xmlrpc.dll</filename> from the XML-RPC.Net
|
|
distribution and copy to the required directories.</para>
|
|
|
|
<para>XML-RPC.Net is compliant with the Common Language Specification
|
|
and so can be used to build XML-RPC clients and servers using any
|
|
CLS-compliant programming language. At the time of writing this means
|
|
the languages provided by Microsoft—C#, VB.Net, JScript, and
|
|
Managed C++—but in the future will include other languages such
|
|
as Eiffel, Perl and Python.</para>
|
|
|
|
<para><function>sample.sumAndDifference</function> client and server
|
|
samples are presented here in both C# and VB.Net. The client samples
|
|
make synchronous calls but it is also possible to make asynchronous
|
|
calls—refer to the XML-RPC.Net documentation for further
|
|
information.</para>
|
|
|
|
<!-- The following text points to a non-existant web page, and will be
|
|
merged in when the link works: Publicly available demo Services
|
|
including the sample Services presented below, are listed at:
|
|
http://www.cookcomputing.com/dotxmlrpcdemos.html -->
|
|
|
|
<section id="xmlrpc-howto-csharp-client">
|
|
<title>A C# Client</title>
|
|
|
|
<para>Save the following code in a file called
|
|
<filename>getSumAndDiffCS.cs</filename>:</para>
|
|
|
|
<programlisting>using System;
|
|
using CookComputing.XmlRpc;
|
|
|
|
public struct Result
|
|
{
|
|
public int sum;
|
|
public int difference;
|
|
}
|
|
|
|
[XmlRpcUri(
|
|
"http://aspx.securedomains.com/cookcomputing/sumanddiffvb.aspx")]
|
|
class Proxy : XmlRpcClientProtocol
|
|
{
|
|
[XmlRpcMethod("sample.sumAndDifference")]
|
|
public Result SumAndDifference(int x, int y)
|
|
{
|
|
return (Result)Invoke("SumAndDifference", new Object[]{x,y})[0];
|
|
}
|
|
}
|
|
|
|
public class App
|
|
{
|
|
public static int Main(string[] args)
|
|
{
|
|
try
|
|
{
|
|
Proxy theProxy = new Proxy();
|
|
Result ret = theProxy.SumAndDifference(5, 3);
|
|
Console.WriteLine("5 + 3 = {0}", ret.sum);
|
|
Console.WriteLine("5 - 3 = {0}", ret.difference);
|
|
}
|
|
catch(XmlRpcClientException cex)
|
|
{
|
|
Console.WriteLine("Client exception: {0} {1}",
|
|
cex.FaultCode, cex.FaultString);
|
|
}
|
|
catch(XmlRpcFaultException fex)
|
|
{
|
|
Console.WriteLine("Server exception: {0} {1}",
|
|
fex.FaultCode, fex.FaultString);
|
|
}
|
|
return 0;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Use the following command to build the client:</para>
|
|
|
|
<programlisting>csc /r:cookcomputing.xmlrpc.dll getSumAndDiffCS.cs</programlisting>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-vbdotnet-client">
|
|
<title>A Visual Basic .NET Client</title>
|
|
|
|
<para>Save the following code in a file called
|
|
<filename>getSumAndDiffVB.vb</filename>:</para>
|
|
|
|
<programlisting>Imports CookComputing.XmlRpc
|
|
|
|
Module Module1
|
|
|
|
Structure Result
|
|
Dim sum, difference As Integer
|
|
End Structure
|
|
|
|
Class <XmlRpcUri( _
|
|
"http://aspx.securedomains.com/cookcomputing/sumanddiffcs.xmlrpc")> _
|
|
Proxy : Inherits XmlRpcClientProtocol
|
|
|
|
Public Function <XmlRpcMethod("sample.sumAndDifference")> _
|
|
SumAndDifference(ByVal x As Integer, ByVal y As Integer) As Result
|
|
Dim results As Object() = Me.Invoke("SumAndDifference", _
|
|
New Object() {x,y})
|
|
Return CType(results(0), Result)
|
|
End Function
|
|
|
|
End Class
|
|
|
|
Sub Main()
|
|
Dim theProxy As New Proxy()
|
|
Try
|
|
Dim ret As Result = theProxy.SumAndDifference(5, 3)
|
|
Console.WriteLine("5 + 3 = {0}", ret.sum)
|
|
Console.WriteLine("5 - 3 = {0}", ret.difference)
|
|
Catch cex As XmlRpcClientException
|
|
Console.WriteLine("Client exception: {0} {1}", _
|
|
cex.FaultCode, cex.FaultString)
|
|
Catch fex As XmlRpcFaultException
|
|
Console.WriteLine("Server exception: {0} {1}", _
|
|
fex.FaultCode, fex.FaultString)
|
|
End Try
|
|
End Sub
|
|
|
|
End Module</programlisting>
|
|
|
|
<para>Use the following command to build the client:</para>
|
|
|
|
<programlisting>vbc /r:cookcomputing.xmlrpc.dll getSumAndDiffVB.vb</programlisting>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-csharp-server">
|
|
<title>A C# Server</title>
|
|
|
|
<para>XML-RPC.Net enables the implementation of XML-RPC Services
|
|
running in the IIS 5 web server environment.</para>
|
|
|
|
<para>Save the following code in a file called
|
|
<filename>SumAndDiffCS.cs</filename>:</para>
|
|
|
|
<programlisting>using System;
|
|
using CookComputing.XmlRpc;
|
|
|
|
public struct Result
|
|
{
|
|
public int sum;
|
|
public int difference;
|
|
}
|
|
|
|
[XmlRpcService(Description=
|
|
"Sample XML-RPC.Net Service implemented in C#")]
|
|
public class SumAndDiffService : XmlRpcService
|
|
{
|
|
[XmlRpcMethod("sample.sumAndDifference", Description=
|
|
"This function takes two integers as arguments and returns an "+
|
|
"XML-RPC struct containing two elements: sum, the sum of the "+
|
|
"two integers, and difference, the difference between the two "+
|
|
"integers")]
|
|
public Result SumAndDifference(int x, int y)
|
|
{
|
|
Result ret;
|
|
ret.sum = x + y;
|
|
ret.difference = x - y;
|
|
return ret;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Use the following to build the client:</para>
|
|
|
|
<programlisting>csc /r:System.Web.dll,cookcomputing.xmlrpc.dll /target:library SumAndDiffCS.cs</programlisting>
|
|
|
|
<para>Create an IIS virtual root, say
|
|
<filename>cookcomputing</filename> for this example, and a
|
|
<filename>bin</filename> directory underneath it. Place the assembly
|
|
(<filename>SumAndDiffCS.dll</filename>) and the XML-RPC.Net assembly
|
|
(<filename>cookcomputing.xmlrpc.dll</filename>) in the
|
|
<filename>bin</filename> directory.</para>
|
|
|
|
<para>Create a text file called <filename>config.web</filename> in
|
|
the <filename>cookcomputing</filename> root directory with the
|
|
following contents:</para>
|
|
|
|
<programlisting><configuration>
|
|
<httphandlers>
|
|
<add verb="*" path="sumanddiffcs.aspx" type="SumAndDiffService,
|
|
SumAndDiffCS" />
|
|
</httphandlers>
|
|
</configuration></programlisting>
|
|
|
|
<para>The Service is now installed and configured. To check this
|
|
navigate your browser to the URL of the Service where you will see an
|
|
automatically generated documentation page.</para>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-vbdotnet-server">
|
|
<title>A Visual Basic .NET Server</title>
|
|
|
|
<para>Save the following code in a file called
|
|
<filename>SumAndDiffVB.cs</filename>:</para>
|
|
|
|
<programlisting>Imports System
|
|
Imports CookComputing.XmlRpc
|
|
|
|
Public Structure Result
|
|
Dim sum, difference As Integer
|
|
End Structure
|
|
|
|
Public Class <XmlRpcService(Description:= _
|
|
"Sample XML-RPC.Net Service implemented in VB.Net")> _
|
|
SumAndDiffService : Inherits XmlRpcService
|
|
|
|
Public Function <XmlRpcMethod("sample.sumAndDifference", _
|
|
Description:= "This function takes two integers as arguments "+ _
|
|
"and returns an XML-RPC struct containing two "+ _
|
|
"elements: sum, the sum of the two integers, and "+ _
|
|
"difference, the difference between the two "+ _
|
|
"integers")> _
|
|
SumAndDifference(ByVal x As Integer, ByVal y As Integer) As Result
|
|
Dim ret As Result
|
|
ret.sum = x + y
|
|
ret.difference = x - y
|
|
Return ret
|
|
End Function
|
|
|
|
End Class</programlisting>
|
|
|
|
<para>Use the following to build the client:</para>
|
|
|
|
<programlisting>vbc /r:System.Web.dll,cookcomputing.xmlrpc.dll /target:library SumAndDiffVB.vb</programlisting>
|
|
|
|
<para>Create an IIS virtual root, say
|
|
<filename>cookcomputing</filename> for this example, and a
|
|
<filename>bin</filename> directory underneath it. Place the assembly
|
|
(<filename>SumAndDiffVB.dll</filename>) and the XML-RPC.Net assembly
|
|
(<filename>cookcomputing.xmlrpc.dll</filename>) in the
|
|
<filename>bin</filename> directory.</para>
|
|
|
|
<para>Create a text file called <filename>config.web</filename> in
|
|
the <filename>cookcomputing</filename> root directory with the
|
|
following contents (note that the entries are case sensitive):</para>
|
|
|
|
<programlisting><configuration>
|
|
<httphandlers>
|
|
<add verb="*" path="sumanddiffvb.aspx" type="SumAndDiffService,
|
|
SumAndDiffVB" />
|
|
</httphandlers>
|
|
</configuration></programlisting>
|
|
|
|
<para>The Service is now installed and configured. To check this
|
|
navigate your browser to the URL of the Service where you will see an
|
|
automatically generated documentation page.</para>
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-ruby">
|
|
<title>Using XML-RPC with Ruby</title>
|
|
|
|
<para><emphasis>(This section of the XML-RPC HOWTO was generously
|
|
provided by Michael Neumann.)</emphasis></para>
|
|
|
|
<para><ulink url="http://www.ruby-lang.org/">Ruby</ulink> is an
|
|
object-oriented scripting language. It already has a major following in
|
|
Japan, and it's becoming popular elsewhere.</para>
|
|
|
|
<para>To use XML-RPC with Ruby, you must first install Yoshida Masato's
|
|
xmlparser module (a wrapper for James Clark's expat parser). This can
|
|
be found at the <ulink url="http://www.ruby-lang.org/en/raa.html">Ruby
|
|
Application Archive</ulink>.</para>
|
|
|
|
<para>Then, you must install <ulink
|
|
url="http://www.s-direktnet.de/homepages/neumann/xmlrpc4r/index.html">xmlrpc4r</ulink>
|
|
using the following commands:</para>
|
|
|
|
<programlisting>bash$ tar -xvzf xmlrpc4r-1_2.tar.gz
|
|
bash$ cd xmlrpc4r-1_2
|
|
bash$ su root -c "ruby install.rb"</programlisting>
|
|
|
|
<section id="xmlrpc-howto-ruby-client">
|
|
<title>A Ruby Client</title>
|
|
|
|
<para>Here's a simple Ruby client:</para>
|
|
|
|
<programlisting>require "xmlrpc/client"
|
|
|
|
# Make an object to represent the XML-RPC server.
|
|
server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php")
|
|
|
|
# Call the remote server and get our result
|
|
result = server.call("sample.sumAndDifference", 5, 3)
|
|
|
|
sum = result["sum"]
|
|
difference = result["difference"]
|
|
|
|
puts "Sum: #{sum}, Difference: #{difference}"</programlisting>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-ruby-server">
|
|
<title>A Ruby Server</title>
|
|
|
|
<para>Here's a simple Ruby server:</para>
|
|
|
|
<programlisting>require "xmlrpc/server"
|
|
|
|
s = XMLRPC::CGIServer.new
|
|
|
|
s.add_hanlder("sample.sumAndDifference") do |a,b|
|
|
{ "sum" => a + b, "difference" => a - b }
|
|
end
|
|
|
|
s.serve</programlisting>
|
|
|
|
<para>This could also have been written as follows:</para>
|
|
|
|
<programlisting>require "xmlrpc/server"
|
|
|
|
s = XMLRPC::CGIServer.new
|
|
|
|
class MyHandler
|
|
def sumAndDifference(a, b)
|
|
{ "sum" => a + b, "difference" => a - b }
|
|
end
|
|
end
|
|
|
|
s.add_handler("sample", MyHandler.new)
|
|
s.serve</programlisting>
|
|
|
|
<para>To run either server in standalone mode, replace the second line
|
|
of code with the following:</para>
|
|
|
|
<programlisting>s = XMLRPC::Server.new(8080)</programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-proprietary">
|
|
<title>Using XML-RPC with Proprietary Languages</title>
|
|
|
|
<para>Implementations of XML-RPC are available for the following
|
|
proprietary programming languages and environments.</para>
|
|
|
|
<section id="xmlrpc-howto-k">
|
|
<title>Using XML-RPC with K</title>
|
|
|
|
<para><emphasis>(This section of the XML-RPC HOWTO was generously
|
|
provided by Christian Langreiter.)</emphasis></para>
|
|
|
|
<para><ulink url="http://www.kx.com/">K</ulink> is a language used in
|
|
finance and database development. To install XML-RPC for K, download
|
|
it from the <ulink url="http://www.langreiter.com/k/kxr">Kx
|
|
website</ulink>. Uncompress and copy the files into the directory in
|
|
which you keep your .k programs.</para>
|
|
|
|
<para>Here's a short client:</para>
|
|
|
|
<programlisting>\l kxr
|
|
server:("localhost";"/cgi-bin/sumAndDifference.cgi");
|
|
.kxr.c[server;"sumAndDifference";2 3]</programlisting>
|
|
|
|
<para>And here's a server:</para>
|
|
|
|
<programlisting>\l kxrsc
|
|
.kxr.sm: ,("sumAndDifference";{.((`sum;+/x);(`difference;-/x))})</programlisting>
|
|
|
|
<para>More examples are included in the distribution.</para>
|
|
</section>
|
|
</section>
|
|
|
|
|
|
<section id="xmlrpc-howto-applist">
|
|
<title>Applications with Built-in XML-RPC Support</title>
|
|
|
|
<para>Several popular Linux applications include support for
|
|
XML-RPC. These have already been described elsewhere, so we mostly
|
|
provide pointers to articles.</para>
|
|
|
|
<section id="xmlrpc-howto-zope">
|
|
<title>Zope</title>
|
|
|
|
<para>Articles on using XML-RPC with Zope are available elsewhere on
|
|
the web:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><ulink
|
|
url="http://www.byte.com/column/BYT19991021S0014">XML-RPC
|
|
Programming with Zope</ulink> by Jon Udell</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><ulink
|
|
url="http://linux.userland.com/stories/storyReader$18">Zope
|
|
XML-RPC</ulink> at UserLand.Com</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-kde">
|
|
<title>KDE 2.0</title>
|
|
|
|
<para>KDE 2.0 includes Kurt Ganroth's <ulink
|
|
url="http://kdecvs.stud.fh-heilbronn.de/cvsweb/kdebase/kxmlrpc/">kxmlrpc
|
|
daemon</ulink>, which allows you to script KDE applications using
|
|
XML-RPC.</para>
|
|
|
|
<para>Here's a short <ulink
|
|
url="http://kdecvs.stud.fh-heilbronn.de/cvsweb/kdebase/kxmlrpc/test/testxmlrpc.py?rev=1.6&content-type=text/x-cvsweb-markup">sample
|
|
application</ulink> in Python. It shows you how to connect to
|
|
kxmlrpc, manipulate your KDE address book, and query the KDE
|
|
trader.</para>
|
|
|
|
<para>If you have any other articles or example code, please see
|
|
<xref linkend="xmlrpc-howto-submitting"/>. We'd like to have more
|
|
information on scripting KDE.</para>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-about">
|
|
<title>About This Document</title>
|
|
|
|
<para>This document is part of the <ulink
|
|
url="http://www.linuxdoc.org/">Linux Documentation
|
|
Project</ulink>. Thanks go to Dave Winer and maintainers of all the
|
|
various XML-RPC libraries.</para>
|
|
|
|
<section id="xmlrpc-howto-versions">
|
|
<title>New Versions of This Document</title>
|
|
|
|
<para>New versions of this document are available at the <ulink
|
|
url="http://www.linuxdoc.org/HOWTO/XML-RPC-HOWTO/index.html">Linux
|
|
Documentation Project</ulink> website.</para>
|
|
|
|
<para>They also provide this manual in alternate formats, including
|
|
<ulink
|
|
url="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/XML-RPC-HOWTO.pdf">PDF</ulink>,
|
|
<ulink
|
|
url="http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html/XML-RPC-HOWTO-html.tar.gz">gzipped
|
|
HTML</ulink> and <ulink
|
|
url="http://www.ibiblio.org/pub/Linux/docs/HOWTO/XML-RPC-HOWTO">ASCII
|
|
text</ulink>.</para>
|
|
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-contributors">
|
|
<title>Contributors to the XML-RPC HOWTO</title>
|
|
|
|
<para>The section on Ruby was contributed by Michael Neumann
|
|
(neumann AT s-direktnet DOT de). The section on K was contributed by
|
|
Christian Langreiter (c DOT langreiter AT synerge DOT at).</para>
|
|
|
|
<para>These contributors are all credited at the beginning of their
|
|
sections.</para>
|
|
</section>
|
|
|
|
<section id="xmlrpc-howto-submitting">
|
|
<title>Submitting Other Snippets</title>
|
|
|
|
<para>If you have a sample client or server in another language or
|
|
environment, we'd love to include it in this manual. To add a new
|
|
entry, we need the following information:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>The URL of the XML-RPC implementation used.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Installation instructions.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>A complete, runnable program.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Compilation instructions, if applicable.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>E-mail your example to the <ulink
|
|
url="http://xmlrpc-c.sourceforge.net/lists.php">xmlrpc-c-devel
|
|
mailing list</ulink> or directly to <ulink
|
|
url="mailto:eric.kidd@pobox.com">Eric Kidd</ulink>.</para>
|
|
|
|
<para>Thank you for your help!</para>
|
|
|
|
</section>
|
|
</section>
|
|
</article>
|