1
<?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">
3
<title>Twisted Documentation: Handling POSTs</title>
4
<link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
8
<h1 class="title">Handling POSTs</h1>
9
<div class="toc"><ol/></div>
13
<p>All of the previous examples have focused on <code>GET</code>
14
requests. Unlike <code>GET</code> requests, <code>POST</code> requests can have
15
a request body - extra data after the request headers; for example, data
16
representing the contents of an HTML form. Twisted Web makes this data available
17
to applications via the <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.web.server.Request.html" title="twisted.web.server.Request">Request</a></code> object.</p>
19
<p>Here's an example web server which renders a static HTML form and then
20
generates a dynamic page when that form is posted back to it. Disclaimer: While
21
it's convenient for this example, it's often not a good idea to make a resource
22
that <code>POST</code>s to itself; this isn't about Twisted Web, but the nature
23
of HTTP in general; if you do this in a real application, make sure you
24
understand the possible negative consequences.</p>
26
<p>As usual, we start with some imports. In addition to the Twisted imports,
27
this example uses the <code>cgi</code> module to <a href="http://en.wikipedia.org/wiki/Cross-site_scripting" shape="rect">escape user-entered
28
content</a> for inclusion in the output.</p>
30
<pre class="python"><p class="py-linenumber">1
35
</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">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Site</span>
36
<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>
37
<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>
39
<span class="py-src-keyword">import</span> <span class="py-src-variable">cgi</span>
42
<p>Next, we'll define a resource which is going to do two things. First, it will
43
respond to <code>GET</code> requests with a static HTML form:</p>
45
<pre class="python"><p class="py-linenumber">1
48
</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">FormPage</span>(<span class="py-src-parameter">Resource</span>):
49
<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>):
50
<span class="py-src-keyword">return</span> <span class="py-src-string">''</span>
53
<p>This is similar to the resource used in a <a href="dynamic-content.html" shape="rect">previous installment</a>. However, we'll now add
54
one more method to give it a second behavior; this <code>render_POST</code>
55
method will allow it to accept <code>POST</code> requests:</p>
57
<pre class="python"><p class="py-linenumber">1
59
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">render_POST</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
60
<span class="py-src-keyword">return</span> <span class="py-src-string">'You submitted: %s'</span> % (<span class="py-src-variable">cgi</span>.<span class="py-src-variable">escape</span>(<span class="py-src-variable">request</span>.<span class="py-src-variable">args</span>[<span class="py-src-string">"the-field"</span>][<span class="py-src-number">0</span>]),)
63
<p>The main thing to note here is the use of <code>request.args</code>. This is
64
a dictionary-like object that provides access to the contents of the form. The
65
keys in this dictionary are the names of inputs in the form. Each value is a
66
list containing strings (since there can be multiple inputs with the same name),
67
which is why we had to extract the first element to pass to
68
<code>cgi.escape</code>. <code>request.args</code> will be populated from form
69
contents whenever a <code>POST</code> request is made with a content type of
70
<code>application/x-www-form-urlencoded</code> or
71
<code>multipart/form-data</code> (it's also populated by query arguments for any
74
<p>Finally, the example just needs the usual site creation and port setup:</p>
76
<pre class="python"><p class="py-linenumber">1
81
</p><span class="py-src-variable">root</span> = <span class="py-src-variable">Resource</span>()
82
<span class="py-src-variable">root</span>.<span class="py-src-variable">putChild</span>(<span class="py-src-string">"form"</span>, <span class="py-src-variable">FormPage</span>())
83
<span class="py-src-variable">factory</span> = <span class="py-src-variable">Site</span>(<span class="py-src-variable">root</span>)
84
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenTCP</span>(<span class="py-src-number">8880</span>, <span class="py-src-variable">factory</span>)
85
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
88
<p>Run the server and visit <a href="http://localhost:8880/form" shape="rect">http://localhost:8880/form</a>, submit the
89
form, and watch it generate a page including the value you entered into the
92
<p>Here's the complete source for the example:</p>
94
<pre class="python"><p class="py-linenumber"> 1
112
</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">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Site</span>
113
<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>
114
<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>
116
<span class="py-src-keyword">import</span> <span class="py-src-variable">cgi</span>
118
<span class="py-src-keyword">class</span> <span class="py-src-identifier">FormPage</span>(<span class="py-src-parameter">Resource</span>):
119
<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>):
120
<span class="py-src-keyword">return</span> <span class="py-src-string">''</span>
122
<span class="py-src-keyword">def</span> <span class="py-src-identifier">render_POST</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
123
<span class="py-src-keyword">return</span> <span class="py-src-string">'You submitted: %s'</span> % (<span class="py-src-variable">cgi</span>.<span class="py-src-variable">escape</span>(<span class="py-src-variable">request</span>.<span class="py-src-variable">args</span>[<span class="py-src-string">"the-field"</span>][<span class="py-src-number">0</span>]),)
125
<span class="py-src-variable">root</span> = <span class="py-src-variable">Resource</span>()
126
<span class="py-src-variable">root</span>.<span class="py-src-variable">putChild</span>(<span class="py-src-string">"form"</span>, <span class="py-src-variable">FormPage</span>())
127
<span class="py-src-variable">factory</span> = <span class="py-src-variable">Site</span>(<span class="py-src-variable">root</span>)
128
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenTCP</span>(<span class="py-src-number">8880</span>, <span class="py-src-variable">factory</span>)
129
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
134
<p><a href="../index.html">Index</a></p>
135
<span class="version">Version: 10.0.0</span>
b'\\ No newline at end of file'