|
1 WebOb |
|
2 +++++ |
|
3 |
|
4 Other documents: |
|
5 |
|
6 * `Reference <reference.html>`_ |
|
7 |
|
8 * Extracted documentation for the `request |
|
9 <class-webob.Request.html>`_ and `response |
|
10 <class-webob.Response.html>`_. |
|
11 |
|
12 * `Differences between the WebOb API and other framework/libraries |
|
13 <differences.html>`_ |
|
14 |
|
15 * `File-serving example <file-example.html>`_ |
|
16 |
|
17 * `Comment middleware example <comment-example.html>`_ |
|
18 |
|
19 .. contents:: |
|
20 |
|
21 .. comment: |
|
22 |
|
23 >>> from dtopt import ELLIPSIS |
|
24 |
|
25 |
|
26 Status & License |
|
27 ================ |
|
28 |
|
29 WebOb is an extraction and refinement of pieces from `Paste |
|
30 <http://pythonpaste.org/>`_. It is under active development. |
|
31 Discussion should happen on the `Paste mailing lists |
|
32 <http://pythonpaste.org/community/>`_, and bugs can go on the `Paste |
|
33 trac instance <http://trac.pythonpaste.org/>`_. |
|
34 |
|
35 WebOb is released under an `MIT-style license <license.html>`_. |
|
36 |
|
37 WebOb is in an svn repository at |
|
38 `http://svn.pythonpaste.org/Paste/WebOb/trunk |
|
39 <http://svn.pythonpaste.org/Paste/WebOb/trunk#egg=WebOb-dev>`_. You |
|
40 can check it out with:: |
|
41 |
|
42 $ svn co http://svn.pythonpaste.org/Paste/WebOb/trunk WebOb |
|
43 |
|
44 Introduction |
|
45 ============ |
|
46 |
|
47 WebOb provides objects for HTTP requests and responses. Specifically |
|
48 it does this by wrapping the `WSGI <http://wsgi.org>`_ request |
|
49 environment and response status/headers/app_iter(body). |
|
50 |
|
51 The request and response objects provide many conveniences for parsing |
|
52 HTTP request and forming HTTP responses. Both objects are read/write: |
|
53 as a result, WebOb is also a nice way to create HTTP requests and |
|
54 parse HTTP responses; however, we won't cover that use case in this |
|
55 document. The `reference documentation <reference.html>`_ shows many |
|
56 examples of creating requests. |
|
57 |
|
58 Request |
|
59 ======= |
|
60 |
|
61 The request object is a wrapper around the `WSGI environ dictionary |
|
62 <http://www.python.org/dev/peps/pep-0333/#environ-variables>`_. This |
|
63 dictionary contains keys for each header, keys that describe the |
|
64 request (including the path and query string), a file-like object for |
|
65 the request body, and a variety of custom keys. You can always access |
|
66 the environ with ``req.environ``. |
|
67 |
|
68 Some of the most important/interesting attributes of a request |
|
69 object: |
|
70 |
|
71 ``req.method``: |
|
72 The request method, e.g., ``'GET'``, ``'POST'`` |
|
73 |
|
74 ``req.GET``: |
|
75 A `dictionary-like object`_ with all the variables in the query |
|
76 string. |
|
77 |
|
78 ``req.POST``: |
|
79 A `dictionary-like object`_ with all the variables in the request |
|
80 body. This only has variables if the request was a ``POST`` and |
|
81 it is a form submission. |
|
82 |
|
83 ``req.params``: |
|
84 A `dictionary-like object`_ with a combination of everything in |
|
85 ``req.GET`` and ``req.POST``. |
|
86 |
|
87 ``req.body``: |
|
88 The contents of the body of the request. This contains the entire |
|
89 request body as a string. This is useful when the request is a |
|
90 ``POST`` that is *not* a form submission, or a request like a |
|
91 ``PUT``. You can also get ``req.body_file`` for a file-like |
|
92 object. |
|
93 |
|
94 ``req.cookies``: |
|
95 A simple dictionary of all the cookies. |
|
96 |
|
97 ``req.headers``: |
|
98 A dictionary of all the headers. This is dictionary is case-insensitive. |
|
99 |
|
100 .. _`dictionary-like object`: #multidict |
|
101 |
|
102 Also, for standard HTTP request headers there are usually attributes, |
|
103 for instance: ``req.accept_language``, ``req.content_length``, |
|
104 ``req.user_agent``, as an example. These properties expose the |
|
105 *parsed* form of each header, for whatever parsing makes sense. For |
|
106 instance, ``req.if_modified_since`` returns a `datetime |
|
107 <http://python.org/doc/current/lib/datetime-datetime.html>`_ object |
|
108 (or None if the header is was not provided). Details are in the |
|
109 `Request reference <class-webob.Request.html>`_. |
|
110 |
|
111 URLs |
|
112 ---- |
|
113 |
|
114 In addition to these attributes, there are several ways to get the URL |
|
115 of the request. I'll show various values for an example URL |
|
116 ``http://localhost/app-root/doc?article_id=10``, where the application |
|
117 is mounted at ``http://localhost/app-root``. |
|
118 |
|
119 ``req.url``: |
|
120 The full request URL, with query string, e.g., |
|
121 ``'http://localhost/app-root/doc?article_id=10'`` |
|
122 |
|
123 ``req.application_url``: |
|
124 The URL of the application (just the SCRIPT_NAME portion of the |
|
125 path, not PATH_INFO). E.g., ``'http://localhost/app-root'`` |
|
126 |
|
127 ``req.host_url``: |
|
128 The URL with the host, e.g., ``'http://localhost'`` |
|
129 |
|
130 ``req.relative_url(url, to_application=False)``: |
|
131 Gives a URL, relative to the current URL. If ``to_application`` |
|
132 is True, then resolves it relative to ``req.application_url``. |
|
133 |
|
134 Methods |
|
135 ------- |
|
136 |
|
137 There are `several methods <class-webob.Request.html#__init__>`_ but |
|
138 only a few you'll use often: |
|
139 |
|
140 ``Request.blank(base_url)``: |
|
141 Creates a new request with blank information, based at the given |
|
142 URL. This can be useful for subrequests and artificial requests. |
|
143 You can also use ``req.copy()`` to copy an existing request, or |
|
144 for subrequests ``req.copy_get()`` which copies the request but |
|
145 always turns it into a GET (which is safer to shrae for |
|
146 subrequests). |
|
147 |
|
148 ``req.get_response(wsgi_application)``: |
|
149 This method calls the given WSGI application with this request, |
|
150 and returns a `Response`_ object. You can also use this for |
|
151 subrequests or testing. |
|
152 |
|
153 Unicode |
|
154 ------- |
|
155 |
|
156 Many of the properties in the request object will return unicode |
|
157 values if the request encoding/charset is provided. The client *can* |
|
158 indicate the charset with something like ``Content-Type: |
|
159 application/x-www-form-urlencoded; charset=utf8``, but browsers seldom |
|
160 set this. You can set the charset with ``req.charset = 'utf8'``, or |
|
161 during instantiation with ``Request(environ, charset='utf8'). If you |
|
162 subclass ``Request`` you can also set ``charset`` as a class-level |
|
163 attribute. |
|
164 |
|
165 If it is set, then ``req.POST``, ``req.GET``, ``req.params``, and |
|
166 ``req.cookies`` will contain unicode strings. Each has a |
|
167 corresponding ``req.str_*`` (like ``req.str_POST``) that is always |
|
168 ``str`` and never unicode. |
|
169 |
|
170 Response |
|
171 ======== |
|
172 |
|
173 The response object looks a lot like the request object, though with |
|
174 some differences. The request object wraps a single ``environ`` |
|
175 object; the response object has three fundamental parts (based on |
|
176 WSGI): |
|
177 |
|
178 ``response.status``: |
|
179 The response code plus message, like ``'200 OK'``. To set the |
|
180 code without the reason, use ``response.status_int = 200``. |
|
181 |
|
182 ``response.headerlist``: |
|
183 A list of all the headers, like ``[('Content-Type', |
|
184 'text/html')]``. There's a case-insensitive `dictionary-like |
|
185 object`_ in ``response.headers`` that also allows you to access |
|
186 these same headers. |
|
187 |
|
188 ``response.app_iter``: |
|
189 An iterable (such as a list or generator) that will produce the |
|
190 content of the response. This is also accessible as |
|
191 ``response.body`` (a string), ``response.unicode_body`` (a |
|
192 unicode object, informed by ``response.charset``), and |
|
193 ``response.body_file`` (a file-like object; writing to it appends |
|
194 to ``app_iter``). |
|
195 |
|
196 Everything else in the object derives from this underlying state. |
|
197 Here's the highlights: |
|
198 |
|
199 ``response.content_type``: |
|
200 The content type *not* including the ``charset`` parameter. |
|
201 Typical use: ``response.content_type = 'text/html'``. You can |
|
202 subclass ``Response`` and add a class-level attribute |
|
203 ``default_content_type`` to set this automatically on |
|
204 instantiation. |
|
205 |
|
206 ``response.charset``: |
|
207 The ``charset`` parameter of the content-type, it also informs |
|
208 encoding in ``response.unicode_body``. |
|
209 ``response.content_type_params`` is a dictionary of all the |
|
210 parameters. |
|
211 |
|
212 ``response.request``: |
|
213 This optional attribute can point to the request object associated |
|
214 with this response object. |
|
215 |
|
216 ``response.set_cookie(key, value, max_age=None, path='/', domain=None, secure=None, httponly=False, version=None, comment=None)``: |
|
217 Set a cookie. The keyword arguments control the various cookie |
|
218 parameters. |
|
219 |
|
220 ``response.delete_cookie(key, path='/', domain=None)``: |
|
221 Delete a cookie from the client. This sets ``max_age`` to 0 and |
|
222 the cookie value to ``''``. |
|
223 |
|
224 ``response.cache_expires(seconds=0)``: |
|
225 This makes this response cachable for the given number of seconds, |
|
226 or if ``seconds`` is 0 then the response is uncacheable (this also |
|
227 sets the ``Expires`` header). |
|
228 |
|
229 ``response(environ, start_response)``: The response object is a WSGI |
|
230 application. As an application, it acts according to how you |
|
231 creat it. It *can* do conditional responses if you pass |
|
232 ``conditional_response=True`` when instantiating (or set that |
|
233 attribute later). It can also do HEAD and Range requests. |
|
234 |
|
235 Headers |
|
236 ------- |
|
237 |
|
238 Like the request, most HTTP response headers are available as |
|
239 properties. These are parsed, so you can do things like |
|
240 ``response.last_modified = os.path.getmtime(filename)``. |
|
241 |
|
242 The details are available in the `extracted Response documentation |
|
243 <class-webob.Response.html>`_. |
|
244 |
|
245 Instantiating the Response |
|
246 -------------------------- |
|
247 |
|
248 Of course most of the time you just want to *make* a response. |
|
249 Generally any attribute of the response can be passed in as a keyword |
|
250 argument to the class; e.g.: |
|
251 |
|
252 .. code-block:: |
|
253 |
|
254 response = Response(body='hello world!', content_type='text/plain') |
|
255 |
|
256 The status defaults to ``'200 OK'``. The content_type does not |
|
257 default to anything, though if you subclass ``Response`` and set |
|
258 ``default_content_type`` you can override this behavior. |
|
259 |
|
260 Exceptions |
|
261 ========== |
|
262 |
|
263 To facilitate error responses like 404 Not Found, the module |
|
264 ``webob.exc`` contains classes for each kind of error response. These |
|
265 include boring but appropriate error bodies. |
|
266 |
|
267 Each class is named ``webob.exc.HTTP*``, where ``*`` is the reason for |
|
268 the error. For instance, ``webob.exc.HTTPNotFound``. It subclasses |
|
269 ``Response``, so you can manipulate the instances in the same way. A |
|
270 typical example is: |
|
271 |
|
272 .. code-block:: |
|
273 |
|
274 response = HTTPNotFound('There is no such resource') |
|
275 # or: |
|
276 response = HTTPMovedPermanently(location=new_url) |
|
277 |
|
278 These are not exceptions unless you are using Python 2.5+, because |
|
279 they are new-style classes which are not allowed as exceptions until |
|
280 Python 2.5. To get an exception object use ``response.exception``. |
|
281 You can use this like: |
|
282 |
|
283 .. code-block:: |
|
284 |
|
285 try: |
|
286 ... stuff ... |
|
287 raise HTTPNotFound('No such resource').exception |
|
288 except HTTPException, e: |
|
289 return e(environ, start_response) |
|
290 |
|
291 The exceptions are still WSGI applications, but you cannot set |
|
292 attributes like ``content_type``, ``charset``, etc. on these exception |
|
293 objects. |
|
294 |
|
295 Multidict |
|
296 ========= |
|
297 |
|
298 Several parts of WebOb use a "multidict"; this is a dictionary where a |
|
299 key can have multiple values. The quintessential example is a query |
|
300 string like ``?pref=red&pref=blue``; the ``pref`` variable has two |
|
301 values: ``red`` and ``blue``. |
|
302 |
|
303 In a multidict, when you do ``request.GET['pref']`` you'll get back |
|
304 only ``'blue'`` (the last value of ``pref``). Sometimes returning a |
|
305 string, and sometimes returning a list, is the cause of frequent |
|
306 exceptions. If you want *all* the values back, use |
|
307 ``request.GET.getall('pref')``. If you want to be sure there is *one |
|
308 and only one* value, use ``request.GET.getone('pref')``, which will |
|
309 raise an exception if there is zero or more than one value for |
|
310 ``pref``. |
|
311 |
|
312 When you use operations like ``request.GET.items()`` you'll get back |
|
313 something like ``[('pref', 'red'), ('pref', 'blue')]``. All the |
|
314 key/value pairs will show up. Similarly ``request.GET.keys()`` |
|
315 returns ``['pref', 'pref']``. Multidict is a view on a list of |
|
316 tuples; all the keys are ordered, and all the values are ordered. |
|
317 |
|
318 Example |
|
319 ======= |
|
320 |
|
321 I haven't figured out the example I want to use here. The |
|
322 `file-serving example`_ shows how to do more advanced HTTP techniques, |
|
323 while the `comment middleware example`_ shows middleware. For |
|
324 applications it's more reasonable to use WebOb in the context of a |
|
325 larger framework. `Pylons <http://pylonshq.com>`_ uses WebOb |
|
326 optionally in 0.9.7+. |
|
327 |
|
328 |