All of the previous examples have focused on GET
requests. Unlike GET
requests, POST
requests can have
a request body - extra data after the request headers; for example, data
representing the contents of an HTML form. Twisted Web makes this data available
to applications via the Request
object.
Here's an example web server which renders a static HTML form and then
generates a dynamic page when that form is posted back to it. Disclaimer: While
it's convenient for this example, it's often not a good idea to make a resource
that POST
s to itself; this isn't about Twisted Web, but the nature
of HTTP in general; if you do this in a real application, make sure you
understand the possible negative consequences.
As usual, we start with some imports. In addition to the Twisted imports,
this example uses the cgi
module to escape user-entered
content for inclusion in the output.
1 2 3 4 5
from twisted.web.server import Site from twisted.web.resource import Resource from twisted.internet import reactor import cgi
Next, we'll define a resource which is going to do two things. First, it will
respond to GET
requests with a static HTML form:
1 2 3
class FormPage(Resource): def render_GET(self, request): return ''
This is similar to the resource used in a previous installment. However, we'll now add
one more method to give it a second behavior; this render_POST
method will allow it to accept POST
requests:
1 2
def render_POST(self, request): return 'You submitted: %s' % (cgi.escape(request.args["the-field"][0]),)
The main thing to note here is the use of request.args
. This is
a dictionary-like object that provides access to the contents of the form. The
keys in this dictionary are the names of inputs in the form. Each value is a
list containing strings (since there can be multiple inputs with the same name),
which is why we had to extract the first element to pass to
cgi.escape
. request.args
will be populated from form
contents whenever a POST
request is made with a content type of
application/x-www-form-urlencoded
or
multipart/form-data
(it's also populated by query arguments for any
type of request).
Finally, the example just needs the usual site creation and port setup:
1 2 3 4 5
root = Resource() root.putChild("form", FormPage()) factory = Site(root) reactor.listenTCP(8880, factory) reactor.run()
Run the server and visit http://localhost:8880/form, submit the form, and watch it generate a page including the value you entered into the single field.
Here's the complete source for the example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
from twisted.web.server import Site from twisted.web.resource import Resource from twisted.internet import reactor import cgi class FormPage(Resource): def render_GET(self, request): return '' def render_POST(self, request): return 'You submitted: %s' % (cgi.escape(request.args["the-field"][0]),) root = Resource() root.putChild("form", FormPage()) factory = Site(root) reactor.listenTCP(8880, factory) reactor.run()