This file is indexed.

/usr/share/doc/python-twisted-web/howto/web-in-60/asynchronous.html is in python-twisted-web 13.2.0-1ubuntu1.

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
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
<title>Twisted Documentation: Asynchronous Responses</title>
<link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
  </head>

  <body bgcolor="white">
    <h1 class="title">Asynchronous Responses</h1>
    <div class="toc"><ol/></div>
    <div class="content">
<span/>

<p>In all of the previous examples, the resource examples presented generated
responses immediately. One of the features of prime interest of Twisted Web,
though, is the ability to generate a response over a longer period of time while
leaving the server free to respond to other requests. In other words,
asynchronously. In this installment, we'll write a resource like this.</p>

<p>A resource that generates a response asynchronously looks like one that
generates a response synchronously in many ways. The same base
class, <code class="API"><a href="http://twistedmatrix.com/documents/13.2.0/api/twisted.web.resource.Resource.html" title="twisted.web.resource.Resource">Resource</a></code>, is used
either way; the same render methods are used. There are three basic differences,
though.</p>

<p>First, instead of returning the string which will be used as the
body of the response, the resource uses <code class="API"><a href="http://twistedmatrix.com/documents/13.2.0/api/twisted.web.http.Request.write.html" title="twisted.web.http.Request.write">Request.write</a></code>. This method can be
called repeatedly. Each call appends another string to the response
body. Second, when the entire response body has been passed
to <code>Request.write</code>, the application must
call <code class="API"><a href="http://twistedmatrix.com/documents/13.2.0/api/twisted.web.http.Request.finish.html" title="twisted.web.http.Request.finish">Request.finish</a></code>. As you might expect
from the name, this ends the response. Finally, in order to make
Twisted Web not end the response as soon as the render method returns,
the render method must return <code>NOT_DONE_YET</code>. Consider this
example:</p>

<pre class="python"><p class="py-linenumber"> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">NOT_DONE_YET</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>

<span class="py-src-keyword">class</span> <span class="py-src-identifier">DelayedResource</span>(<span class="py-src-parameter">Resource</span>):
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">_delayedRender</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
        <span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">&quot;&lt;html&gt;&lt;body&gt;Sorry to keep you waiting.&lt;/body&gt;&lt;/html&gt;&quot;</span>)
        <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
        <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">5</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_delayedRender</span>, <span class="py-src-variable">request</span>)
        <span class="py-src-keyword">return</span> <span class="py-src-variable">NOT_DONE_YET</span>
</pre>

<p>If you're not familiar with the reactor <code class="API"><a href="http://twistedmatrix.com/documents/13.2.0/api/twisted.internet.interfaces.IReactorTime.callLater.html" title="twisted.internet.interfaces.IReactorTime.callLater">callLater</a></code>
method, all you really need to know about it to understand this
example is that the above usage of it arranges to
have <code>self._delayedRender(request)</code> run about 5 seconds
after <code>callLater</code> is invoked from this render method and
that it returns immediately.</p>

<p>All three of the elements mentioned earlier can be seen in this
example. The resource uses <code>Request.write</code> to set the
response body. It uses <code>Request.finish</code> after the entire
body has been specified (all with just one call to write in this
case). Lastly, it returns <code>NOT_DONE_YET</code> from its render
method. So there you have it, asynchronous rendering with Twisted
Web.</p>

<p>Here's a complete rpy script based on this resource class (see the <a href="rpy-scripts.html" shape="rect">previous example</a> if you need a reminder about rpy
scripts):</p>

<pre class="python"><p class="py-linenumber"> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">NOT_DONE_YET</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>

<span class="py-src-keyword">class</span> <span class="py-src-identifier">DelayedResource</span>(<span class="py-src-parameter">Resource</span>):
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">_delayedRender</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
        <span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">&quot;&lt;html&gt;&lt;body&gt;Sorry to keep you waiting.&lt;/body&gt;&lt;/html&gt;&quot;</span>)
        <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()

    <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
        <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">5</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_delayedRender</span>, <span class="py-src-variable">request</span>)
        <span class="py-src-keyword">return</span> <span class="py-src-variable">NOT_DONE_YET</span>

<span class="py-src-variable">resource</span> = <span class="py-src-variable">DelayedResource</span>()
</pre>

<p>Drop this source into a <code>.rpy</code> file and fire up a server
using <code>twistd -n web --path /directory/containing/script/.</code>
You'll see that loading the page takes 5 seconds. If you try to load a
second before the first completes, it will also take 5 seconds from
the time you request it (but it won't be delayed by any other
outstanding requests).</p>

<p>Something else to consider when generating responses asynchronously is that
the client may not wait around to get the response to its
request. A <a href="interrupted.html" shape="rect">subsequent example</a> demonstrates how
to detect that the client has abandoned the request and that the server
shouldn't bother to finish generating its response.</p>

</div>

    <p><a href="../index.html">Index</a></p>
    <span class="version">Version: 13.2.0</span>
  </body>
</html>