Project

General

Profile

Request » History » Version 5

Elmer de Looff, 2012-04-27 12:18
POST explained, still needs 'arrays' and file upload

1 1 Jan Klopper
h1. Request
2 1 Jan Klopper
3 5 Elmer de Looff
{{>toc}}
4 5 Elmer de Looff
5 3 Elmer de Looff
The @Request@ object is an abstraction of the incoming HTTP request. This allows one simple interface that is independent of the underlying server that µWeb runs on (either [[Standalone]] using BaseHTTPServer, or [[Apache]] mode on @mod_python@).
6 1 Jan Klopper
7 4 Elmer de Looff
From PageMaker methods, the request object is accessible as the @self.req@ member. The request object contains all the information about the incoming request: query arguments, post data, cookies and environment data. It is also the object where you define cookies that need to be provided to the client.
8 1 Jan Klopper
9 4 Elmer de Looff
h1. Query arguments
10 4 Elmer de Looff
11 4 Elmer de Looff
All query arguments provided by the client are present on the request object. They are also accessible directly on the [[PageMaker]] object. The following code demonstrates both ways to access a query argument:
12 4 Elmer de Looff
13 5 Elmer de Looff
<pre><code class="html">
14 5 Elmer de Looff
...
15 5 Elmer de Looff
<form>
16 5 Elmer de Looff
  <label for="name">Name: </label><input id="name" name="name" />
17 5 Elmer de Looff
  <input type="submit" value="Tell us your name" />
18 5 Elmer de Looff
</form>
19 5 Elmer de Looff
...
20 5 Elmer de Looff
</code></pre>
21 5 Elmer de Looff
22 1 Jan Klopper
<pre><code class="python">
23 5 Elmer de Looff
def NameFromQuery(self):
24 4 Elmer de Looff
  # Retrieves the 'name' argument from the request object:
25 4 Elmer de Looff
  name = self.req.vars['get'].getfirst('name')
26 4 Elmer de Looff
27 4 Elmer de Looff
  # Retrieves the 'name' argument directly from the PageMaker instance (linked to the request):
28 4 Elmer de Looff
  name = self.get.getfirst('name')
29 4 Elmer de Looff
  return name
30 4 Elmer de Looff
</code></pre>
31 4 Elmer de Looff
32 4 Elmer de Looff
Using the @getfirst@ method, you get a single string returned from the query argument mapping, or a @None@ if no such value exists. Much like a dictionary's @get@ method, you can provide a second argument to the method, and have that returned instead as the default. 
33 4 Elmer de Looff
34 1 Jan Klopper
Now, HTTP allows the client to provide the same query argument multiple times. Using @getfirst@ you would only get the very first defined argument. So a request that looks like @http://example.org/group?name=Bob&name=Mark&name=Jenny@ would only return 'Bob' in the previous example. To get all their names printed, you can use the following:
35 1 Jan Klopper
36 5 Elmer de Looff
<pre><code class="html">
37 5 Elmer de Looff
...
38 5 Elmer de Looff
<form action="/group">
39 5 Elmer de Looff
  <h2>Names in this group</h2>
40 5 Elmer de Looff
  <!-- These would likely be generated with Javascript, but written here for demonstrative purposes -->
41 5 Elmer de Looff
  <label for="name_1">Name: </label><input id="name_1" name="name" />
42 5 Elmer de Looff
  <label for="name_2">Name: </label><input id="name_2" name="name" />
43 5 Elmer de Looff
  <label for="name_3">Name: </label><input id="name_3" name="name" />
44 5 Elmer de Looff
  <input type="submit" value="Send these names" />
45 5 Elmer de Looff
</form>
46 5 Elmer de Looff
...
47 5 Elmer de Looff
</code></pre>
48 5 Elmer de Looff
49 1 Jan Klopper
<pre><code class="python">
50 5 Elmer de Looff
def MemberNames(self):
51 1 Jan Klopper
  names = self.get.getlist('name')
52 1 Jan Klopper
  return ', '.join(names)
53 1 Jan Klopper
</code></pre>
54 1 Jan Klopper
55 1 Jan Klopper
This returns a neat comma-separated string with all the provided names. The @getlist@ method does not take a default, but will instead return an empty list when there are no values for the requested argument name.
56 1 Jan Klopper
57 5 Elmer de Looff
h1. Post data
58 1 Jan Klopper
59 5 Elmer de Looff
Submitted form data is available on the request object as well. The interface is similar to that of the query arguments, and the @FieldStorage@ class already present in the @cgi@ module. If we take our initial example form handler, but now receive the data through HTTP POST, the code would look like this:
60 1 Jan Klopper
61 5 Elmer de Looff
<pre><code class="html">
62 5 Elmer de Looff
...
63 5 Elmer de Looff
<form method="post">
64 5 Elmer de Looff
  <label for="name">Name: </label><input id="name" name="name" />
65 5 Elmer de Looff
  <input type="submit" value="Tell us your name" />
66 5 Elmer de Looff
</form>
67 5 Elmer de Looff
...
68 5 Elmer de Looff
</code></pre>
69 1 Jan Klopper
70 5 Elmer de Looff
<pre><code class="python">
71 5 Elmer de Looff
def NameFromPost(self):
72 5 Elmer de Looff
  # Retrieves the 'name' value from the request object:
73 5 Elmer de Looff
  name = self.req.vars['post'].getfirst('name')
74 1 Jan Klopper
75 5 Elmer de Looff
  # Retrieves the 'name' value directly from the PageMaker instance (linked to the request):
76 5 Elmer de Looff
  name = self.post.getfirst('name')
77 5 Elmer de Looff
  return name
78 5 Elmer de Looff
</code></pre>
79 1 Jan Klopper
80 5 Elmer de Looff
Like with the query arguments, @getfirst@ accepts a second argument that provides a default other than @None@.
81 1 Jan Klopper
82 5 Elmer de Looff
Multiple values are again possible in the FieldStorage, but these work exactly like they do in the query arguments, so please have a look at those.
83 2 Elmer de Looff
84 5 Elmer de Looff
h2. Uploading files
85 1 Jan Klopper
86 5 Elmer de Looff
h2. Structured data using POST
87 5 Elmer de Looff
88 5 Elmer de Looff
h1. Cookies
89 5 Elmer de Looff
90 1 Jan Klopper
self.cookies contains the cookies send by the browser, as the interface to create them from the server.
91 1 Jan Klopper
92 1 Jan Klopper
h3. Retrieving a cookie
93 1 Jan Klopper
You can fetch the content of cookie by accessig the self.cookie dict with the name of the desired cookie as its key.
94 1 Jan Klopper
The returned cookie object has a value member containing the actual value of the requested cookie.
95 1 Jan Klopper
<pre>
96 1 Jan Klopper
<code class="python">
97 1 Jan Klopper
self.cookies['sample'].value
98 1 Jan Klopper
</code>
99 1 Jan Klopper
</pre>
100 1 Jan Klopper
101 5 Elmer de Looff
h1. Environment
102 1 Jan Klopper
103 1 Jan Klopper
The env variable is a dictionary containing the following items;
104 1 Jan Klopper
* CONTENT_TYPE
105 1 Jan Klopper
* CONTENT_LENGTH
106 1 Jan Klopper
* HTTP_COOKIE
107 1 Jan Klopper
* HTTP_HOST
108 1 Jan Klopper
* HTTP_REFERER
109 1 Jan Klopper
* HTTP_USER_AGENT
110 1 Jan Klopper
* PATH_INFO
111 1 Jan Klopper
* QUERY_STRING
112 1 Jan Klopper
* REMOTE_ADDR
113 1 Jan Klopper
* REQUEST_METHOD
114 1 Jan Klopper
* UWEB_MODE 'STANDALONE' / 'MOD_PYTHON'
115 1 Jan Klopper
116 5 Elmer de Looff
h2. Extended environment
117 5 Elmer de Looff
118 1 Jan Klopper
If more detail is required about the environment, you can issue a call to the self.req.ExtendedEnvironment() method, which will inject more details into the env var. This is a much slower operation than the normal env call, so that's why its tucked away in a separate method.
119 1 Jan Klopper
120 1 Jan Klopper
* AUTH_TYPE
121 1 Jan Klopper
* CONNECTION_ID
122 1 Jan Klopper
* DOCUMENT_ROOT
123 1 Jan Klopper
* RAW_REQUEST
124 1 Jan Klopper
* REMOTE_HOST
125 1 Jan Klopper
* REMOTE_USER
126 1 Jan Klopper
* SERVER_NAME
127 1 Jan Klopper
* SERVER_PORT
128 1 Jan Klopper
* SERVER_LOCAL_NAME
129 1 Jan Klopper
* SERVER_LOCAL_IP
130 2 Elmer de Looff
* SERVER_PROTOCOL
131 1 Jan Klopper
132 1 Jan Klopper
And in case of a @mod_python@ setup you will also get:
133 1 Jan Klopper
* MODPYTHON_HANDLER
134 1 Jan Klopper
* MODPYTHON_INTERPRETER
135 1 Jan Klopper
* MODPYTHON_PHASE
136 5 Elmer de Looff
137 5 Elmer de Looff
h1. Setting cookies