This file is indexed.

/usr/share/doc/python-quixote-doc/web-services.html is in python-quixote-doc 2.7~b2-1.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<?xml version="1.0" encoding="us-ascii" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
<title>Implementing Web Services with Quixote</title>
<link rel="stylesheet" href="default.css" type="text/css" />
</head>
<body>
<div class="document" id="implementing-web-services-with-quixote">
<h1 class="title">Implementing Web Services with Quixote</h1>
<p>This document will show you how to implement Web services using
Quixote.</p>
<div class="section" id="an-xml-rpc-service">
<h1><a name="an-xml-rpc-service">An XML-RPC Service</a></h1>
<p>XML-RPC is the simplest protocol commonly used to expose a Web
service.  In XML-RPC, there are a few basic data types such as
integers, floats, strings, and dates, and a few aggregate types such
as arrays and structs.  The xmlrpclib module, part of the Python 2.2
standard library and available separately from
<a class="reference" href="http://www.pythonware.com/products/xmlrpc/">http://www.pythonware.com/products/xmlrpc/</a>, converts between Python's
standard data types and the XML-RPC data types.</p>
<table class="table" frame="border" rules="all">
<colgroup>
<col width="40%" />
<col width="60%" />
</colgroup>
<tbody valign="top">
<tr><td>XML-RPC Type</td>
<td>Python Type or Class</td>
</tr>
<tr><td>&lt;int&gt;</td>
<td>int</td>
</tr>
<tr><td>&lt;double&gt;</td>
<td>float</td>
</tr>
<tr><td>&lt;string&gt;</td>
<td>string</td>
</tr>
<tr><td>&lt;array&gt;</td>
<td>list</td>
</tr>
<tr><td>&lt;struct&gt;</td>
<td>dict</td>
</tr>
<tr><td>&lt;boolean&gt;</td>
<td>xmlrpclib.Boolean</td>
</tr>
<tr><td>&lt;base64&gt;</td>
<td>xmlrpclib.Binary</td>
</tr>
<tr><td>&lt;dateTime&gt;</td>
<td>xmlrpclib.DateTime</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="making-xml-rpc-calls">
<h1><a name="making-xml-rpc-calls">Making XML-RPC Calls</a></h1>
<p>Making an XML-RPC call using xmlrpclib is easy.  An XML-RPC server
lives at a particular URL, so the first step is to create an
xmlrpclib.ServerProxy object pointing at that URL.</p>
<pre class="literal-block">
&gt;&gt;&gt; import xmlrpclib
&gt;&gt;&gt; s = xmlrpclib.ServerProxy(
             'http://www.stuffeddog.com/speller/speller-rpc.cgi')
</pre>
<p>Now you can simply make a call to the spell-checking service offered
by this server:</p>
<pre class="literal-block">
&gt;&gt;&gt; s.speller.spellCheck('my speling isnt gud', {})
[{'word': 'speling', 'suggestions': ['apeling', 'spelding',
  'spelling', 'sperling', 'spewing', 'spiling'], 'location': 4},
{'word': 'isnt', 'suggestions': [``isn't'', 'ist'], 'location': 12}]
&gt;&gt;&gt; 
</pre>
<p>This call results in the following XML being sent:</p>
<pre class="literal-block">
&lt;?xml version='1.0'?&gt;
&lt;methodCall&gt;
     &lt;methodName&gt;speller.spellCheck&lt;/methodName&gt;
     &lt;params&gt;
         &lt;param&gt;
                &lt;value&gt;&lt;string&gt;my speling isnt gud&lt;/string&gt;&lt;/value&gt;
         &lt;/param&gt;
         &lt;param&gt;
                 &lt;value&gt;&lt;struct&gt;&lt;/struct&gt;&lt;/value&gt;
         &lt;/param&gt;
     &lt;/params&gt;
&lt;/methodCall&gt;
</pre>
</div>
<div class="section" id="writing-a-quixote-service">
<h1><a name="writing-a-quixote-service">Writing a Quixote Service</a></h1>
<p>In the quixote.util module, Quixote provides a function,
<tt class="literal"><span class="pre">xmlrpc(request,</span> <span class="pre">func)</span></tt>, that processes the body of an XML-RPC
request.  <tt class="literal"><span class="pre">request</span></tt> is the HTTPRequest object that Quixote passes to
every function it invokes.  <tt class="literal"><span class="pre">func</span></tt> is a user-supplied function that
receives the name of the XML-RPC method being called and a tuple
containing the method's parameters.  If there's a bug in the function
you supply and it raises an exception, the <tt class="literal"><span class="pre">xmlrpc()</span></tt> function will
catch the exception and return a <tt class="literal"><span class="pre">Fault</span></tt> to the remote caller.</p>
<p>Here's an example of implementing a simple XML-RPC handler with a
single method, <tt class="literal"><span class="pre">get_time()</span></tt>, that simply returns the current
time.  The first task is to expose a URL for accessing the service.</p>
<pre class="literal-block">
from quixote.directory import Directory
from quixote.util import xmlrpc
from quixote import get_request

class RPCDirectory(Directory):

    _q_exports = ['rpc']

    def rpc (self):
        return xmlrpc(get_request(), rpc_process)

def rpc_process (meth, params):
    ...
</pre>
<p>When the above code is placed in the __init__.py file for the Python
package corresponding to your Quixote application, it exposes the URL
<tt class="literal"><span class="pre">http://&lt;hostname&gt;/rpc</span></tt> as the access point for the XML-RPC service.</p>
<p>Next, we need to fill in the contents of the <tt class="literal"><span class="pre">rpc_process()</span></tt>
function:</p>
<pre class="literal-block">
import time

def rpc_process (meth, params):
    if meth == 'get_time':
        # params is ignored
        now = time.gmtime(time.time())
        return xmlrpclib.DateTime(now)
    else:
        raise RuntimeError, &quot;Unknown XML-RPC method: %r&quot; % meth
</pre>
<p><tt class="literal"><span class="pre">rpc_process()</span></tt> receives the method name and the parameters, and its
job is to run the right code for the method, returning a result that
will be marshalled into XML-RPC.  The body of <tt class="literal"><span class="pre">rpc_process()</span></tt> will
therefore usually be an <tt class="literal"><span class="pre">if</span></tt> statement that checks the name of the
method, and calls another function to do the actual work.  In this case,
<tt class="literal"><span class="pre">get_time()</span></tt> is very simple so the two lines of code it requires are
simply included in the body of <tt class="literal"><span class="pre">rpc_process()</span></tt>.</p>
<p>If the method name doesn't belong to a supported method, execution
will fall through to the <tt class="literal"><span class="pre">else</span></tt> clause, which will raise a
RuntimeError exception.  Quixote's <tt class="literal"><span class="pre">xmlrpc()</span></tt> will catch this
exception and report it to the caller as an XML-RPC fault, with the
error code set to 1.</p>
<p>As you add additional XML-RPC services, the <tt class="literal"><span class="pre">if</span></tt> statement in
<tt class="literal"><span class="pre">rpc_process()</span></tt> will grow more branches.  You might be tempted to pass
the method name to <tt class="literal"><span class="pre">getattr()</span></tt> to select a method from a module or
class.  That would work, too, and avoids having a continually growing
set of branches, but you should be careful with this and be sure that
there are no private methods that a remote caller could access.  I
generally prefer to have the <tt class="literal"><span class="pre">if...</span> <span class="pre">elif...</span> <span class="pre">elif...</span> <span class="pre">else</span></tt> blocks, for
three reasons: 1) adding another branch isn't much work, 2) it's
explicit about the supported method names, and 3) there won't be any
security holes in doing so.</p>
<p>An alternative approach is to have a dictionary mapping method names
to the corresponding functions and restrict the legal method names 
to the keys of this dictionary:</p>
<pre class="literal-block">
def echo (*params):
    # Just returns the parameters it's passed
    return params

def get_time ():
    now = time.gmtime(time.time())
    return xmlrpclib.DateTime(now)

methods = {'echo' : echo, 
           'get_time' : get_time}

def rpc_process (meth, params):
    func = methods.get[meth]
    if methods.has_key(meth):
        # params is ignored
        now = time.gmtime(time.time())
        return xmlrpclib.DateTime(now)
    else:
        raise RuntimeError, &quot;Unknown XML-RPC method: %r&quot; % meth
</pre>
<p>This approach works nicely when there are many methods and the
<tt class="literal"><span class="pre">if...elif...else</span></tt> statement would be unworkably long.</p>
</div>
</div>
</body>
</html>