<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="Description" content="An event-driven networking engine written in Python and MIT licensed." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Creating XML-RPC Servers and Clients with Twisted — Twisted 16.0.0 documentation</title>
<link rel="stylesheet" href="../../_static/twistedtrac.css" type="text/css" />
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../../',
VERSION: '16.0.0',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../../_static/jquery.js"></script>
<script type="text/javascript" src="../../_static/underscore.js"></script>
<script type="text/javascript" src="../../_static/doctools.js"></script>
<link rel="top" title="Twisted 16.0.0 documentation" href="../../index.html" />
<link rel="up" title="Developer Guides" href="index.html" />
<link rel="next" title="Twisted Web In 60 Seconds" href="web-in-60/index.html" />
<link rel="prev" title="HTML Templating with twisted.web.template" href="twisted-templates.html" />
<!-- Can stuff between these comments go? -->
<link rel="search" href="/trac/search" />
<link rel="help" href="/trac/wiki/TracGuide" />
<link rel="alternate" href="/trac/wiki/Documentation?format=txt" type="text/x-trac-wiki" title="Plain Text" />
<link rel="start" href="/trac/wiki" />
<script type="text/javascript" src="/trac/chrome/common/js/jquery.js"></script><script type="text/javascript" src="/trac/chrome/common/js/trac.js"></script><script type="text/javascript" src="/trac/chrome/common/js/search.js"></script>
<!-- the following script tag is a holdover frome Trac, which shouldn't be needed in Sphinx
<script type="text/javascript">
$(document).ready(function() {
$("#content").find("h1,h2,h3,h4,h5,h6").addAnchor("Link to this section");
});
</script>
-->
<!-- Can stuff between these comments go? -->
</head>
<body>
<div id="banner">
<div id="top_grad">
</div>
<div id="tab">
<a href="http://twistedmatrix.com/trac/wiki">HOME</a>
<a href="http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions">FAQ</a>
<a href="/">DOCS</a>
<a href="http://twistedmatrix.com/trac/wiki/Downloads">DOWNLOAD</a>
</div>
<div id="header">
<a id="logo" href="http://twistedmatrix.com/trac/"><img src="../../_static/trac_banner.png" alt="Twisted" /></a>
</div>
<!-- taking this out for now, but might use
the space for something else later
-->
<!--
<form id="topsearch" action="/trac/search" method="get"><div>
<label for="proj-search">Search:</label>
<input type="text" id="proj-search" name="q" size="10" value="" />
<input type="submit" value="Search" />
<input type="hidden" name="wiki" value="on" />
<input type="hidden" name="changeset" value="on" />
<input type="hidden" name="ticket" value="on" />
</div></form>
-->
<div id="metanav" class="nav">
<ul>
<li> </li>
<!-- taking this out for now, but might use
the space for something else later
-->
<!--
<li class="first">logged in as khorn</li><li class=""><a href="/trac/logout">Logout</a></li><li class=""><a href="/trac/wiki/TracGuide">Help/Guide</a></li><li class=""><a href="/trac/about">About Trac</a></li><li class="last"><a href="/trac/account">My Account</a></li>
-->
</ul>
</div>
</div>
<!-- mainnav -->
<div id="mainnav" class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="web-in-60/index.html" title="Twisted Web In 60 Seconds"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="twisted-templates.html" title="HTML Templating with twisted.web.template"
accesskey="P">previous</a> |</li>
<li><a href="../../index.html">Twisted 16.0.0 documentation</a> »</li>
<li><a href="../index.html" >Twisted Web</a> »</li>
<li><a href="index.html" accesskey="U">Developer Guides</a> »</li>
</ul>
</div>
<div id="main">
<div id="ctxtnav" class="nav">
<h2>Wiki Navigation</h2>
<ul>
<li>
</li>
<!-- taking this out for now, but might use
the space for something else later
-->
<!--
<li><a href="/trac/wiki/WikiStart">Start Page</a></li>
<li><a href="/trac/wiki/TitleIndex">Index by Title</a></li>
<li><a href="/trac/wiki/RecentChanges">Index by Date</a></li>
<li class="last">
<a href="/trac/wiki/Documentation?action=diff&version=15">Last Change</a>
</li>
-->
</ul>
<hr />
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div id="current-docs-container" style="display: none">
<em>
<a id="current-docs-link">
Go to the latest version of this document.
</a>
</em>
</div>
<div class="body">
<div class="section" id="creating-xml-rpc-servers-and-clients-with-twisted">
<h1>Creating XML-RPC Servers and Clients with Twisted<a class="headerlink" href="#creating-xml-rpc-servers-and-clients-with-twisted" title="Permalink to this headline">¶</a></h1>
<div class="section" id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
<p><a class="reference external" href="http://www.xmlrpc.com">XML-RPC</a> is a simple request/reply protocol
that runs over HTTP. It is simple, easy to implement and supported by most programming
languages. Twisted’s XML-RPC support is implemented using the`xmlrpclib <<a class="reference external" href="http://docs.python.org/library/xmlrpclib.html">http://docs.python.org/library/xmlrpclib.html</a>>`_ library that is
included with Python 2.2 and later.</p>
</div>
<div class="section" id="creating-a-xml-rpc-server">
<h2>Creating a XML-RPC server<a class="headerlink" href="#creating-a-xml-rpc-server" title="Permalink to this headline">¶</a></h2>
<p>Making a server is very easy - all you need to do is inherit from <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.xmlrpc.XMLRPC.html">twisted.web.xmlrpc.XMLRPC</a> .
You then create methods beginning with <code class="docutils literal"><span class="pre">xmlrpc_</span></code> . The methods’
arguments determine what arguments it will accept from XML-RPC clients.
The result is what will be returned to the clients.</p>
<p>Methods published via XML-RPC can return all the basic XML-RPC
types, such as strings, lists and so on (just return a regular python
integer, etc). They can also raise exceptions or return Failure instances to indicate an
error has occurred, or <code class="docutils literal"><span class="pre">Binary</span></code> , <code class="docutils literal"><span class="pre">Boolean</span></code> or <code class="docutils literal"><span class="pre">DateTime</span></code>
instances (all of these are the same as the respective classes in xmlrpclib. In
addition, XML-RPC published methods can return <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.internet.defer.Deferred.html">Deferred</a> instances whose results are one of the above. This allows
you to return results that can’t be calculated immediately, such as database queries.
See the <a class="reference internal" href="../../core/howto/defer.html"><em>Deferred documentation</em></a> for more
details.</p>
<p><a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.xmlrpc.XMLRPC.html">XMLRPC</a> instances
are Resource objects, and they can thus be published using a Site. The
following example has two methods published via XML-RPC, <code class="docutils literal"><span class="pre">add(a,</span> <span class="pre">b)</span></code> and <code class="docutils literal"><span class="pre">echo(x)</span></code> .</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.web</span> <span class="kn">import</span> <span class="n">xmlrpc</span><span class="p">,</span> <span class="n">server</span>
<span class="k">class</span> <span class="nc">Example</span><span class="p">(</span><span class="n">xmlrpc</span><span class="o">.</span><span class="n">XMLRPC</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> An example object to be published.</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="nf">xmlrpc_echo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Return all passed args.</span>
<span class="sd"> """</span>
<span class="k">return</span> <span class="n">x</span>
<span class="k">def</span> <span class="nf">xmlrpc_add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Return sum of arguments.</span>
<span class="sd"> """</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
<span class="k">def</span> <span class="nf">xmlrpc_fault</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Raise a Fault indicating that the procedure should not be used.</span>
<span class="sd"> """</span>
<span class="k">raise</span> <span class="n">xmlrpc</span><span class="o">.</span><span class="n">Fault</span><span class="p">(</span><span class="mi">123</span><span class="p">,</span> <span class="s">"The fault procedure is faulty."</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">reactor</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">Example</span><span class="p">()</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="mi">7080</span><span class="p">,</span> <span class="n">server</span><span class="o">.</span><span class="n">Site</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>After we run this command, we can connect with a client and send commands
to the server:</p>
<div class="highlight-pycon"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">xmlrpclib</span>
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">xmlrpclib</span><span class="o">.</span><span class="n">Server</span><span class="p">(</span><span class="s">'http://localhost:7080/'</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">echo</span><span class="p">(</span><span class="s">"lala"</span><span class="p">)</span>
<span class="go">'lala'</span>
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="go">3</span>
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">fault</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="c">...</span>
<span class="gr">xmlrpclib.Fault</span>: <span class="n"><Fault 123: 'The fault procedure is faulty.'></span>
<span class="go">>>></span>
</pre></div>
</div>
<p>If the <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.server.Request.html">Request</a> object is
needed by an <code class="docutils literal"><span class="pre">xmlrpc_*</span></code> method, it can be made available using
the <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.xmlrpc.withRequest.html">twisted.web.xmlrpc.withRequest</a> decorator. When
using this decorator, the method will be passed the request object as the first
argument, before any XML-RPC parameters. For example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.web.xmlrpc</span> <span class="kn">import</span> <span class="n">XMLRPC</span><span class="p">,</span> <span class="n">withRequest</span>
<span class="kn">from</span> <span class="nn">twisted.web.server</span> <span class="kn">import</span> <span class="n">Site</span>
<span class="k">class</span> <span class="nc">Example</span><span class="p">(</span><span class="n">XMLRPC</span><span class="p">):</span>
<span class="nd">@withRequest</span>
<span class="k">def</span> <span class="nf">xmlrpc_headerValue</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">headerName</span><span class="p">):</span>
<span class="k">return</span> <span class="n">request</span><span class="o">.</span><span class="n">requestHeaders</span><span class="o">.</span><span class="n">getRawHeaders</span><span class="p">(</span><span class="n">headerName</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">reactor</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="mi">7080</span><span class="p">,</span> <span class="n">Site</span><span class="p">(</span><span class="n">Example</span><span class="p">()))</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>XML-RPC resources can also be part of a normal Twisted web server, using
resource scripts. The following is an example of such a resource script:</p>
<p><a class="reference download internal" href="../../_downloads/xmlquote.rpy"><code class="xref download docutils literal"><span class="pre">xmlquote.rpy</span></code></a></p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.web</span> <span class="kn">import</span> <span class="n">xmlrpc</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="k">def</span> <span class="nf">getQuote</span><span class="p">():</span>
<span class="k">return</span> <span class="s">"What are you talking about, William?"</span>
<span class="k">class</span> <span class="nc">Quoter</span><span class="p">(</span><span class="n">xmlrpc</span><span class="o">.</span><span class="n">XMLRPC</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">xmlrpc_quote</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="n">getQuote</span><span class="p">()</span>
<span class="n">resource</span> <span class="o">=</span> <span class="n">Quoter</span><span class="p">()</span>
</pre></div>
</div>
<div class="section" id="using-xml-rpc-sub-handlers">
<h3>Using XML-RPC sub-handlers<a class="headerlink" href="#using-xml-rpc-sub-handlers" title="Permalink to this headline">¶</a></h3>
<p>XML-RPC resource can be nested so that one handler calls another if
a method with a given prefix is called. For example, to add support
for an XML-RPC method <code class="docutils literal"><span class="pre">date.time()</span></code> to
the <code class="docutils literal"><span class="pre">Example</span></code> class, you could do the
following:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">twisted.web</span> <span class="kn">import</span> <span class="n">xmlrpc</span><span class="p">,</span> <span class="n">server</span>
<span class="k">class</span> <span class="nc">Example</span><span class="p">(</span><span class="n">xmlrpc</span><span class="o">.</span><span class="n">XMLRPC</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> An example object to be published.</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="nf">xmlrpc_echo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Return all passed args.</span>
<span class="sd"> """</span>
<span class="k">return</span> <span class="n">x</span>
<span class="k">def</span> <span class="nf">xmlrpc_add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Return sum of arguments.</span>
<span class="sd"> """</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
<span class="k">class</span> <span class="nc">Date</span><span class="p">(</span><span class="n">xmlrpc</span><span class="o">.</span><span class="n">XMLRPC</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Serve the XML-RPC 'time' method.</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="nf">xmlrpc_time</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">"""</span>
<span class="sd"> Return UNIX time.</span>
<span class="sd"> """</span>
<span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">reactor</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">Example</span><span class="p">()</span>
<span class="n">date</span> <span class="o">=</span> <span class="n">Date</span><span class="p">()</span>
<span class="n">r</span><span class="o">.</span><span class="n">putSubHandler</span><span class="p">(</span><span class="s">'date'</span><span class="p">,</span> <span class="n">date</span><span class="p">)</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="mi">7080</span><span class="p">,</span> <span class="n">server</span><span class="o">.</span><span class="n">Site</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>By default, a period (‘.’) separates the prefix from the method
name, but you can use a different character by overriding the <code class="docutils literal"><span class="pre">XMLRPC.separator</span></code> data member in your base
XML-RPC server. XML-RPC servers may be nested to arbitrary depths
using this method.</p>
</div>
<div class="section" id="using-your-own-procedure-getter">
<h3>Using your own procedure getter<a class="headerlink" href="#using-your-own-procedure-getter" title="Permalink to this headline">¶</a></h3>
<p>Sometimes, you want to implement your own policy of getting the end implementation.
E.g. just like sub-handlers you want to divide the implementations into separate classes but
may not want to introduce <code class="docutils literal"><span class="pre">XMLRPC.separator</span></code> in the procedure name.
In such cases just override the <code class="docutils literal"><span class="pre">lookupProcedure(self,</span> <span class="pre">procedurePath)</span></code>
method and return the correct callable.
Raise <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.xmlrpc.NoSuchFunction.html">twisted.web.xmlrpc.NoSuchFunction</a> otherwise.</p>
<p><a class="reference download internal" href="../../_downloads/xmlrpc-customized.py"><code class="xref download docutils literal"><span class="pre">xmlrpc-customized.py</span></code></a></p>
<div class="highlight-python"><div class="highlight"><pre>from twisted.web import xmlrpc, server
class EchoHandler:
def echo(self, x):
"""
Return all passed args
"""
return x
class AddHandler:
def add(self, a, b):
"""
Return sum of arguments.
"""
return a + b
class Example(xmlrpc.XMLRPC):
"""
An example of using you own policy to fetch the handler
"""
def __init__(self):
xmlrpc.XMLRPC.__init__(self)
self._addHandler = AddHandler()
self._echoHandler = EchoHandler()
#We keep a dict of all relevant
#procedure names and callable.
self._procedureToCallable = {
'add':self._addHandler.add,
'echo':self._echoHandler.echo
}
def lookupProcedure(self, procedurePath):
try:
return self._procedureToCallable[procedurePath]
except KeyError, e:
raise xmlrpc.NoSuchFunction(self.NOT_FOUND,
"procedure %s not found" % procedurePath)
def listProcedures(self):
"""
Since we override lookupProcedure, its suggested to override
listProcedures too.
"""
return ['add', 'echo']
if __name__ == '__main__':
from twisted.internet import reactor
r = Example()
reactor.listenTCP(7080, server.Site(r))
reactor.run()
</pre></div>
</div>
</div>
<div class="section" id="adding-xml-rpc-introspection-support">
<h3>Adding XML-RPC Introspection support<a class="headerlink" href="#adding-xml-rpc-introspection-support" title="Permalink to this headline">¶</a></h3>
<p>XML-RPC has an
informal <a class="reference external" href="http://tldp.org/HOWTO/XML-RPC-HOWTO/xmlrpc-howto-interfaces.html">IntrospectionAPI</a> that specifies three methods in a <code class="docutils literal"><span class="pre">system</span></code>
sub-handler which allow a client to query a server about the server’s
API. Adding Introspection support to
the <code class="docutils literal"><span class="pre">Example</span></code> class is easy using
the <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.xmlrpc.XMLRPCIntrospection.html">XMLRPCIntrospection</a> class:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.web</span> <span class="kn">import</span> <span class="n">xmlrpc</span><span class="p">,</span> <span class="n">server</span>
<span class="k">class</span> <span class="nc">Example</span><span class="p">(</span><span class="n">xmlrpc</span><span class="o">.</span><span class="n">XMLRPC</span><span class="p">):</span>
<span class="sd">"""An example object to be published."""</span>
<span class="k">def</span> <span class="nf">xmlrpc_echo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="sd">"""Return all passed args."""</span>
<span class="k">return</span> <span class="n">x</span>
<span class="n">xmlrpc_echo</span><span class="o">.</span><span class="n">signature</span> <span class="o">=</span> <span class="p">[[</span><span class="s">'string'</span><span class="p">,</span> <span class="s">'string'</span><span class="p">],</span>
<span class="p">[</span><span class="s">'int'</span><span class="p">,</span> <span class="s">'int'</span><span class="p">],</span>
<span class="p">[</span><span class="s">'double'</span><span class="p">,</span> <span class="s">'double'</span><span class="p">],</span>
<span class="p">[</span><span class="s">'array'</span><span class="p">,</span> <span class="s">'array'</span><span class="p">],</span>
<span class="p">[</span><span class="s">'struct'</span><span class="p">,</span> <span class="s">'struct'</span><span class="p">]]</span>
<span class="k">def</span> <span class="nf">xmlrpc_add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="sd">"""Return sum of arguments."""</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
<span class="n">xmlrpc_add</span><span class="o">.</span><span class="n">signature</span> <span class="o">=</span> <span class="p">[[</span><span class="s">'int'</span><span class="p">,</span> <span class="s">'int'</span><span class="p">,</span> <span class="s">'int'</span><span class="p">],</span>
<span class="p">[</span><span class="s">'double'</span><span class="p">,</span> <span class="s">'double'</span><span class="p">,</span> <span class="s">'double'</span><span class="p">]]</span>
<span class="n">xmlrpc_add</span><span class="o">.</span><span class="n">help</span> <span class="o">=</span> <span class="s">"Add the arguments and return the sum."</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">reactor</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">Example</span><span class="p">()</span>
<span class="n">xmlrpc</span><span class="o">.</span><span class="n">addIntrospection</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="mi">7080</span><span class="p">,</span> <span class="n">server</span><span class="o">.</span><span class="n">Site</span><span class="p">(</span><span class="n">r</span><span class="p">))</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>Note the method attributes <code class="docutils literal"><span class="pre">help</span></code>
and <code class="docutils literal"><span class="pre">signature</span></code> which are used by the
Introspection API methods <code class="docutils literal"><span class="pre">system.methodHelp</span></code>
and <code class="docutils literal"><span class="pre">system.methodSignature</span></code> respectively. If
no <code class="docutils literal"><span class="pre">help</span></code> attribute is specified, the
method’s documentation string is used instead.</p>
</div>
</div>
<div class="section" id="soap-support">
<h2>SOAP Support<a class="headerlink" href="#soap-support" title="Permalink to this headline">¶</a></h2>
<p>From the point of view of a Twisted developer, there is little difference
between XML-RPC support and SOAP support. Here is an example of SOAP usage:</p>
<p><a class="reference download internal" href="../../_downloads/soap.rpy"><code class="xref download docutils literal"><span class="pre">soap.rpy</span></code></a></p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.web</span> <span class="kn">import</span> <span class="n">soap</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="k">def</span> <span class="nf">getQuote</span><span class="p">():</span>
<span class="k">return</span> <span class="s">"That beverage, sir, is off the hizzy."</span>
<span class="k">class</span> <span class="nc">Quoter</span><span class="p">(</span><span class="n">soap</span><span class="o">.</span><span class="n">SOAPPublisher</span><span class="p">):</span>
<span class="sd">"""Publish one method, 'quote'."""</span>
<span class="k">def</span> <span class="nf">soap_quote</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="n">getQuote</span><span class="p">()</span>
<span class="n">resource</span> <span class="o">=</span> <span class="n">Quoter</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="section" id="creating-an-xml-rpc-client">
<h2>Creating an XML-RPC Client<a class="headerlink" href="#creating-an-xml-rpc-client" title="Permalink to this headline">¶</a></h2>
<p>XML-RPC clients in Twisted are meant to look as something which will be
familiar either to <code class="docutils literal"><span class="pre">xmlrpclib</span></code> or to Perspective Broker users,
taking features from both, as appropriate. There are two major deviations
from the <code class="docutils literal"><span class="pre">xmlrpclib</span></code> way which should be noted:</p>
<ol class="arabic simple">
<li>No implicit <code class="docutils literal"><span class="pre">/RPC2</span></code> . If the services uses this path for the
XML-RPC calls, then it will have to be given explicitly.</li>
<li>No magic <code class="docutils literal"><span class="pre">__getattr__</span></code> : calls must be made by an explicit
<code class="docutils literal"><span class="pre">callRemote</span></code> .</li>
</ol>
<p>The interface Twisted presents to XML-RPC client is that of a proxy
object: <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.xmlrpc.Proxy.html">twisted.web.xmlrpc.Proxy</a> . The
constructor for the object receives a URL: it must be an HTTP or HTTPS
URL. When an XML-RPC service is described, the URL to that service
will be given there.</p>
<p>Having a proxy object, one can just call the <code class="docutils literal"><span class="pre">callRemote</span></code> method,
which accepts a method name and a variable argument list (but no named
arguments, as these are not supported by XML-RPC). It returns a deferred,
which will be called back with the result. If there is any error, at any
level, the errback will be called. The exception will be the relevant Twisted
error in the case of a problem with the underlying connection (for example,
a timeout), <code class="docutils literal"><span class="pre">IOError</span></code> containing the status and message in the case
of a non-200 status or a <code class="docutils literal"><span class="pre">xmlrpclib.Fault</span></code> in the case of an
XML-RPC level problem.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.web.xmlrpc</span> <span class="kn">import</span> <span class="n">Proxy</span>
<span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">reactor</span>
<span class="k">def</span> <span class="nf">printValue</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
<span class="k">print</span> <span class="nb">repr</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">printError</span><span class="p">(</span><span class="n">error</span><span class="p">):</span>
<span class="k">print</span> <span class="s">'error'</span><span class="p">,</span> <span class="n">error</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="n">proxy</span> <span class="o">=</span> <span class="n">Proxy</span><span class="p">(</span><span class="s">'http://advogato.org/XMLRPC'</span><span class="p">)</span>
<span class="n">proxy</span><span class="o">.</span><span class="n">callRemote</span><span class="p">(</span><span class="s">'test.sumprod'</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">addCallbacks</span><span class="p">(</span><span class="n">printValue</span><span class="p">,</span> <span class="n">printError</span><span class="p">)</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>prints:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="p">[</span><span class="mi">8</span><span class="p">,</span> <span class="mi">15</span><span class="p">]</span>
</pre></div>
</div>
</div>
<div class="section" id="serving-soap-and-xml-rpc-simultaneously">
<h2>Serving SOAP and XML-RPC simultaneously<a class="headerlink" href="#serving-soap-and-xml-rpc-simultaneously" title="Permalink to this headline">¶</a></h2>
<p><a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.xmlrpc.XMLRPC.html">twisted.web.xmlrpc.XMLRPC</a> and <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.soap.SOAPPublisher.html">twisted.web.soap.SOAPPublisher</a> are both <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.resource.Resource.html">Resource</a> s. So, to serve both XML-RPC and
SOAP in the one web server, you can use the <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.resource.IResource.putChild.html">putChild</a> method of Resource.</p>
<p>The following example uses an empty <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.resource.Resource.html">resource.Resource</a> as the root resource for
a <a class="api reference external" href="https://twistedmatrix.com/documents/16.0.0/api/twisted.web.server.Site.html">Site</a> , and then
adds <code class="docutils literal"><span class="pre">/RPC2</span></code> and <code class="docutils literal"><span class="pre">/SOAP</span></code> paths to it.</p>
<p><a class="reference download internal" href="../../_downloads/xmlAndSoapQuote.py"><code class="xref download docutils literal"><span class="pre">xmlAndSoapQuote.py</span></code></a></p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">twisted.web</span> <span class="kn">import</span> <span class="n">soap</span><span class="p">,</span> <span class="n">xmlrpc</span><span class="p">,</span> <span class="n">resource</span><span class="p">,</span> <span class="n">server</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="k">def</span> <span class="nf">getQuote</span><span class="p">():</span>
<span class="k">return</span> <span class="s">"Victory to the burgeois, you capitalist swine!"</span>
<span class="k">class</span> <span class="nc">XMLRPCQuoter</span><span class="p">(</span><span class="n">xmlrpc</span><span class="o">.</span><span class="n">XMLRPC</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">xmlrpc_quote</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="n">getQuote</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">SOAPQuoter</span><span class="p">(</span><span class="n">soap</span><span class="o">.</span><span class="n">SOAPPublisher</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">soap_quote</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="n">getQuote</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">reactor</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">resource</span><span class="o">.</span><span class="n">Resource</span><span class="p">()</span>
<span class="n">root</span><span class="o">.</span><span class="n">putChild</span><span class="p">(</span><span class="s">'RPC2'</span><span class="p">,</span> <span class="n">XMLRPCQuoter</span><span class="p">())</span>
<span class="n">root</span><span class="o">.</span><span class="n">putChild</span><span class="p">(</span><span class="s">'SOAP'</span><span class="p">,</span> <span class="n">SOAPQuoter</span><span class="p">())</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="mi">7080</span><span class="p">,</span> <span class="n">server</span><span class="o">.</span><span class="n">Site</span><span class="p">(</span><span class="n">root</span><span class="p">))</span>
<span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<p>Refer to <a class="reference internal" href="using-twistedweb.html#web-howto-using-twistedweb-development"><span>Twisted Web
Development</span></a> for more details about Resources.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="../../index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Creating XML-RPC Servers and Clients with Twisted</a><ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#creating-a-xml-rpc-server">Creating a XML-RPC server</a><ul>
<li><a class="reference internal" href="#using-xml-rpc-sub-handlers">Using XML-RPC sub-handlers</a></li>
<li><a class="reference internal" href="#using-your-own-procedure-getter">Using your own procedure getter</a></li>
<li><a class="reference internal" href="#adding-xml-rpc-introspection-support">Adding XML-RPC Introspection support</a></li>
</ul>
</li>
<li><a class="reference internal" href="#soap-support">SOAP Support</a></li>
<li><a class="reference internal" href="#creating-an-xml-rpc-client">Creating an XML-RPC Client</a></li>
<li><a class="reference internal" href="#serving-soap-and-xml-rpc-simultaneously">Serving SOAP and XML-RPC simultaneously</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="twisted-templates.html"
title="previous chapter">HTML Templating with twisted.web.template</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="web-in-60/index.html"
title="next chapter">Twisted Web In 60 Seconds</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../../_sources/web/howto/xmlrpc.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../../search.html" method="get">
<p>
<input type="text" name="q" size="18" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</p>
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
</div>
<div id="footer"><hr />
<div>
</div>
<p class="left2">
Site design<br />
By <a href="http://huw.ugbox.net/">huw.wilkins.</a>
</p>
<p class="right"></p>
</div>
<script type="text/javascript">
if (window.location.pathname.indexOf('/current/') == -1) {
<!-- Give the user a link to this page, but in the current version of the docs. -->
var link = document.getElementById('current-docs-link');
link.href = window.location.pathname.replace(/\/\d+\.\d+\.\d+/, '/current');
<!-- And make it visible -->
var container = document.getElementById('current-docs-container');
container.style.display = '';
delete link;
delete container;
}
</script>
</body>
</html>
Copyright 2K16 - 2K18 Indonesian Hacker Rulez