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