WebOb Reference
+++++++++++++++

.. contents::

.. comment:

    >>> from doctest import ELLIPSIS

Introduction
============

This document covers all the details of the Request and Response
objects.  It is written to be testable with `doctest
<http://python.org/doc/current/lib/module-doctest.html>`_ -- this
affects the flavor of the documentation, perhaps to its detriment.
But it also means you can feel confident that the documentation is
correct.

This is a somewhat different approach to reference documentation
compared to the extracted documentation for the `request
<class-webob.Request.html>`_ and `response
<class-webob.Response.html>`_.

Request
=======

The primary object in WebOb is ``webob.Request``, a wrapper around a
`WSGI environment <http://www.python.org/dev/peps/pep-0333/>`_.

The basic way you create a request object is simple enough:

.. code-block:: python

   >>> from webob import Request
   >>> environ = {'wsgi.url_scheme': 'http', ...}  #doctest: +SKIP
   >>> req = Request(environ)                      #doctest: +SKIP

(Note that the WSGI environment is a dictionary with a dozen required
keys, so it's a bit lengthly to show a complete example of what it
would look like -- usually your WSGI server will create it.)

The request object *wraps* the environment; it has very little
internal state of its own.  Instead attributes you access read and
write to the environment dictionary.

You don't have to understand the details of WSGI to use this library;
this library handles those details for you.  You also don't have to
use this exclusively of other libraries.  If those other libraries
also keep their state in the environment, multiple wrappers can
coexist.  Examples of libraries that can coexist include
`paste.wsgiwrappers.Request
<http://pythonpaste.org/class-paste.wsgiwrappers.WSGIRequest.html>`_
(used by Pylons) and `yaro.Request
<http://lukearno.com/projects/yaro/>`_.

The WSGI environment has a number of required variables.  To make it
easier to test and play around with, the ``Request`` class has a
constructor that will fill in a minimal environment:

.. code-block:: python

   >>> req = Request.blank('/article?id=1')
   >>> from pprint import pprint
   >>> pprint(req.environ)
   {'HTTP_HOST': 'localhost:80',
    'PATH_INFO': '/article',
    'QUERY_STRING': 'id=1',
    'REQUEST_METHOD': 'GET',
    'SCRIPT_NAME': '',
    'SERVER_NAME': 'localhost',
    'SERVER_PORT': '80',
    'SERVER_PROTOCOL': 'HTTP/1.0',
    'wsgi.errors': <open file '<stderr>', mode 'w' at ...>,
    'wsgi.input': <...IO... object at ...>,
    'wsgi.multiprocess': False,
    'wsgi.multithread': False,
    'wsgi.run_once': False,
    'wsgi.url_scheme': 'http',
    'wsgi.version': (1, 0)}

Request Body
------------

``req.body`` is a file-like object that gives the body of the request
(e.g., a POST form, the body of a PUT, etc).  It's kind of boring to
start, but you can set it to a string and that will be turned into a
file-like object.  You can read the entire body with
``req.body``.

.. code-block:: python

    >>> hasattr(req.body_file, 'read')
    True
    >>> req.body
    ''
    >>> req.method = 'PUT'
    >>> req.body = 'test'
    >>> hasattr(req.body_file, 'read')
    True
    >>> req.body
    'test'

Method & URL
------------

All the normal parts of a request are also accessible through the
request object:

.. code-block:: python

    >>> req.method
    'PUT'
    >>> req.scheme
    'http'
    >>> req.script_name  # The base of the URL
    ''
    >>> req.script_name = '/blog' # make it more interesting
    >>> req.path_info    # The yet-to-be-consumed part of the URL
    '/article'
    >>> req.content_type # Content-Type of the request body
    ''
    >>> print req.remote_user  # The authenticated user (there is none set)
    None
    >>> print req.remote_addr  # The remote IP
    None
    >>> req.host
    'localhost:80'
    >>> req.host_url
    'http://localhost'
    >>> req.application_url
    'http://localhost/blog'
    >>> req.path_url
    'http://localhost/blog/article'
    >>> req.url
    'http://localhost/blog/article?id=1'
    >>> req.path
    '/blog/article'
    >>> req.path_qs
    '/blog/article?id=1'
    >>> req.query_string
    'id=1'

You can make new URLs:

.. code-block:: python

    >>> req.relative_url('archive')
    'http://localhost/blog/archive'

For parsing the URLs, it is often useful to deal with just the next
path segment on PATH_INFO:

.. code-block:: python

    >>> req.path_info_peek() # Doesn't change request
    'article'
    >>> req.path_info_pop()  # Does change request!
    'article'
    >>> req.script_name
    '/blog/article'
    >>> req.path_info
    ''

Headers
-------

All request headers are available through a dictionary-like object
``req.headers``.  Keys are case-insensitive.

.. code-block:: python

    >>> req.headers['Content-Type'] = 'application/x-www-urlencoded'
    >>> sorted(req.headers.items())
    [('Content-Length', '4'), ('Content-Type', 'application/x-www-urlencoded'), ('Host', 'localhost:80')]
    >>> req.environ['CONTENT_TYPE']
    'application/x-www-urlencoded'

Query & POST variables
----------------------

Requests can have variables in one of two locations: the query string
(``?id=1``), or in the body of the request (generally a POST form).
Note that even POST requests can have a query string, so both kinds of
variables can exist at the same time.  Also, a variable can show up
more than once, as in ``?check=a&check=b``.

For these variables WebOb uses a `MultiDict
<class-webob.multidict.MultiDict.html>`_, which is basically a
dictionary wrapper on a list of key/value pairs.  It looks like a
single-valued dictionary, but you can access all the values of a key
with ``.getall(key)`` (which always returns a list, possibly an empty
list).  You also get all key/value pairs when using ``.items()`` and
all values with ``.values()``.

Some examples:

.. code-block:: python

    >>> req = Request.blank('/test?check=a&check=b&name=Bob')
    >>> req.GET
    MultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')])
    >>> req.GET['check']
    u'b'
    >>> req.GET.getall('check')
    [u'a', u'b']
    >>> req.GET.items()
    [(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')]

We'll have to create a request body and change the method to get
POST.  Until we do that, the variables are boring:

.. code-block:: python

    >>> req.POST
    <NoVars: Not a form request>
    >>> req.POST.items()  # NoVars can be read like a dict, but not written
    []
    >>> req.method = 'POST'
    >>> req.body = 'name=Joe&email=joe@example.com'
    >>> req.POST
    MultiDict([(u'name', u'Joe'), (u'email', u'joe@example.com')])
    >>> req.POST['name']
    u'Joe'

Often you won't care where the variables come from.  (Even if you care
about the method, the location of the variables might not be
important.)  There is a dictionary called ``req.params`` that
contains variables from both sources:

.. code-block:: python

    >>> req.params
    NestedMultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob'), (u'name', u'Joe'), (u'email', u'joe@example.com')])
    >>> req.params['name']
    u'Bob'
    >>> req.params.getall('name')
    [u'Bob', u'Joe']
    >>> for name, value in req.params.items():
    ...     print '%s: %r' % (name, value)
    check: u'a'
    check: u'b'
    name: u'Bob'
    name: u'Joe'
    email: u'joe@example.com'

The ``POST`` and ``GET`` nomenclature is historical -- ``req.GET`` can
be used for non-GET requests to access query parameters, and
``req.POST`` can also be used for PUT requests with the appropriate
Content-Type.

    >>> req = Request.blank('/test?check=a&check=b&name=Bob')
    >>> req.method = 'PUT'
    >>> req.body = body = 'var1=value1&var2=value2&rep=1&rep=2'
    >>> req.environ['CONTENT_LENGTH'] = str(len(req.body))
    >>> req.environ['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
    >>> req.GET
    MultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')])
    >>> req.POST
    MultiDict([(u'var1', u'value1'), (u'var2', u'value2'), (u'rep', u'1'), (u'rep', u'2')])

Unicode Variables
~~~~~~~~~~~~~~~~~

Submissions are non-unicode (``str``) strings, unless some character
set is indicated.  A client can indicate the character set with
``Content-Type: application/x-www-form-urlencoded; charset=utf8``, but
very few clients actually do this (sometimes XMLHttpRequest requests
will do this, as JSON is always UTF8 even when a page is served with a
different character set).  You can force a charset, which will affect
all the variables:

.. code-block:: python

    >>> req.charset = 'utf8'
    >>> req.GET
    MultiDict([(u'check', u'a'), (u'check', u'b'), (u'name', u'Bob')])

Cookies
-------

Cookies are presented in a simple dictionary.  Like other variables,
they will be decoded into Unicode strings if you set the charset.

.. code-block:: python

    >>> req.headers['Cookie'] = 'test=value'
    >>> req.cookies
    MultiDict([(u'test', u'value')])

Modifying the request
---------------------

The headers are all modifiable, as are other environmental variables
(like ``req.remote_user``, which maps to
``request.environ['REMOTE_USER']``).

If you want to copy the request you can use ``req.copy()``; this
copies the ``environ`` dictionary, and the request body from
``environ['wsgi.input']``.

The method ``req.remove_conditional_headers(remove_encoding=True)``
can be used to remove headers that might result in a ``304 Not
Modified`` response.  If you are writing some intermediary it can be
useful to avoid these headers.  Also if ``remove_encoding`` is true
(the default) then any ``Accept-Encoding`` header will be removed,
which can result in gzipped responses.

Header Getters
--------------

In addition to ``req.headers``, there are attributes for most of the
request headers defined by the HTTP 1.1 specification.  These
attributes often return parsed forms of the headers.

Accept-* headers
~~~~~~~~~~~~~~~~

There are several request headers that tell the server what the client
accepts.  These are ``accept`` (the Content-Type that is accepted),
``accept_charset`` (the charset accepted), ``accept_encoding``
(the Content-Encoding, like gzip, that is accepted), and
``accept_language`` (generally the preferred language of the client).

The objects returned support containment to test for acceptability.
E.g.:

.. code-block:: python

    >>> 'text/html' in req.accept
    True

Because no header means anything is potentially acceptable, this is
returning True.  We can set it to see more interesting behavior (the
example means that ``text/html`` is okay, but
``application/xhtml+xml`` is preferred):

.. code-block:: python

    >>> req.accept = 'text/html;q=0.5, application/xhtml+xml;q=1'
    >>> req.accept
    <MIMEAccept('text/html;q=0.5, application/xhtml+xml')>
    >>> 'text/html' in req.accept
    True

There are a few methods for different strategies of finding a match.

.. code-block:: python

    >>> req.accept.best_match(['text/html', 'application/xhtml+xml'])
    'application/xhtml+xml'

If we just want to know everything the client prefers, in the order it
is preferred:

.. code-block:: python

    >>> list(req.accept)
    ['application/xhtml+xml', 'text/html']

For languages you'll often have a "fallback" language.  E.g., if there's
nothing better then use ``en-US`` (and if ``en-US`` is okay, ignore
any less preferrable languages):

.. code-block:: python

    >>> req.accept_language = 'es, pt-BR'
    >>> req.accept_language.best_match(['en-GB', 'en-US'], default_match='en-US')
    'en-US'
    >>> req.accept_language.best_match(['es', 'en-US'], default_match='en-US')
    'es'

Your fallback language must appear both in the ``offers`` and as the
``default_match`` to insure that it is returned as a best match if the
client specified a preference for it.

.. code-block:: python

    >>> req.accept_language = 'en-US;q=0.5, en-GB;q=0.2'
    >>> req.accept_language.best_match(['en-GB'], default_match='en-US')
    'en-GB'
    >>> req.accept_language.best_match(['en-GB', 'en-US'], default_match='en-US')
    'en-US'

Conditional Requests
~~~~~~~~~~~~~~~~~~~~

There a number of ways to make a conditional request.  A conditional
request is made when the client has a document, but it is not sure if
the document is up to date.  If it is not, it wants a new version.  If
the document is up to date then it doesn't want to waste the
bandwidth, and expects a ``304 Not Modified`` response.

ETags are generally the best technique for these kinds of requests;
this is an opaque string that indicates the identity of the object.
For instance, it's common to use the mtime (last modified) of the file,
plus the number of bytes, and maybe a hash of the filename (if there's
a possibility that the same URL could point to two different
server-side filenames based on other variables).  To test if a 304
response is appropriate, you can use:

.. code-block:: python

    >>> server_token = 'opaque-token'
    >>> server_token in req.if_none_match # You shouldn't return 304
    False
    >>> req.if_none_match = server_token
    >>> req.if_none_match
    <ETag opaque-token>
    >>> server_token in req.if_none_match # You *should* return 304
    True

For date-based comparisons If-Modified-Since is used:

.. code-block:: python

    >>> from webob import UTC
    >>> from datetime import datetime
    >>> req.if_modified_since = datetime(2006, 1, 1, 12, 0, tzinfo=UTC)
    >>> req.headers['If-Modified-Since']
    'Sun, 01 Jan 2006 12:00:00 GMT'
    >>> server_modified = datetime(2005, 1, 1, 12, 0, tzinfo=UTC)
    >>> req.if_modified_since and req.if_modified_since >= server_modified
    True

For range requests there are two important headers, If-Range (which is
form of conditional request) and Range (which requests a range).  If
the If-Range header fails to match then the full response (not a
range) should be returned:

.. code-block:: python

    >>> req.if_range
    <Empty If-Range>
    >>> req.if_range.match(etag='some-etag', last_modified=datetime(2005, 1, 1, 12, 0))
    True
    >>> req.if_range = 'opaque-etag'
    >>> req.if_range.match(etag='other-etag')
    False
    >>> req.if_range.match(etag='opaque-etag')
    True

You can also pass in a response object with:

.. code-block:: python

    >>> from webob import Response
    >>> res = Response(etag='opaque-etag')
    >>> req.if_range.match_response(res)
    True

To get the range information:

    >>> req.range = 'bytes=0-100'
    >>> req.range
    <Range ranges=(0, 101)>
    >>> cr = req.range.content_range(length=1000)
    >>> cr.start, cr.stop, cr.length
    (0, 101, 1000)

Note that the range headers use *inclusive* ranges (the last byte
indexed is included), where Python always uses a range where the last
index is excluded from the range.  The ``.stop`` index is in the
Python form.

Another kind of conditional request is a request (typically PUT) that
includes If-Match or If-Unmodified-Since.  In this case you are saying
"here is an update to a resource, but don't apply it if someone else
has done something since I last got the resource".  If-Match means "do
this if the current ETag matches the ETag I'm giving".
If-Unmodified-Since means "do this if the resource has remained
unchanged".

.. code-block:: python

    >>> server_token in req.if_match # No If-Match means everything is ok
    True
    >>> req.if_match = server_token
    >>> server_token in req.if_match # Still OK
    True
    >>> req.if_match = 'other-token'
    >>> # Not OK, should return 412 Precondition Failed:
    >>> server_token in req.if_match
    False

For more on this kind of conditional request, see `Detecting the Lost
Update Problem Using Unreserved Checkout
<http://www.w3.org/1999/04/Editing/>`_.

Calling WSGI Applications
-------------------------

The request object can be used to make handy subrequests or test
requests against WSGI applications.  If you want to make subrequests,
you should copy the request (with ``req.copy()``) before sending it to
multiple applications, since applications might modify the request
when they are run.

There's two forms of the subrequest.  The more primitive form is
this:

.. code-block:: python

    >>> req = Request.blank('/')
    >>> def wsgi_app(environ, start_response):
    ...     start_response('200 OK', [('Content-type', 'text/plain')])
    ...     return ['Hi!']
    >>> req.call_application(wsgi_app)
    ('200 OK', [('Content-type', 'text/plain')], ['Hi!'])

Note it returns ``(status_string, header_list, app_iter)``.  If
``app_iter.close()`` exists, it is your responsibility to call it.

A handier response can be had with:

.. code-block:: python

    >>> res = req.get_response(wsgi_app)
    >>> res
    <Response ... 200 OK>
    >>> res.status
    '200 OK'
    >>> res.headers
    ResponseHeaders([('Content-type', 'text/plain')])
    >>> res.body
    'Hi!'

You can learn more about this response object in the Response_ section.

Ad-Hoc Attributes
-----------------

You can assign attributes to your request objects.  They will all go
in ``environ['webob.adhoc_attrs']`` (a dictionary).

.. code-block:: python

    >>> req = Request.blank('/')
    >>> req.some_attr = 'blah blah blah'
    >>> new_req = Request(req.environ)
    >>> new_req.some_attr
    'blah blah blah'
    >>> req.environ['webob.adhoc_attrs']
    {'some_attr': 'blah blah blah'}

Response
========

The ``webob.Response`` object contains everything necessary to make a
WSGI response.  Instances of it are in fact WSGI applications, but it
can also represent the result of calling a WSGI application (as noted
in `Calling WSGI Applications`_).  It can also be a way of
accumulating a response in your WSGI application.

A WSGI response is made up of a status (like ``200 OK``), a list of
headers, and a body (or iterator that will produce a body).

Core Attributes
---------------

The core attributes are unsurprising:

.. code-block:: python

    >>> from webob import Response
    >>> res = Response()
    >>> res.status
    '200 OK'
    >>> res.headerlist
    [('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '0')]
    >>> res.body
    ''

You can set any of these attributes, e.g.:

.. code-block:: python

    >>> res.status = 404
    >>> res.status
    '404 Not Found'
    >>> res.status_code
    404
    >>> res.headerlist = [('Content-type', 'text/html')]
    >>> res.body = 'test'
    >>> print res
    404 Not Found
    Content-type: text/html
    Content-Length: 4
    <BLANKLINE>
    test
    >>> res.body = u"test"
    Traceback (most recent call last):
        ...
    TypeError: You cannot set Response.body to a unicode object (use Response.text)
    >>> res.text = u"test"
    Traceback (most recent call last):
        ...
    AttributeError: You cannot access Response.text unless charset is set
    >>> res.charset = 'utf8'
    >>> res.text = u"test"
    >>> res.body
    'test'

You can set any attribute with the constructor, like
``Response(charset='utf8')``

Headers
-------

In addition to ``res.headerlist``, there is dictionary-like view on
the list in ``res.headers``:

.. code-block:: python

    >>> res.headers
    ResponseHeaders([('Content-Type', 'text/html; charset=utf8'), ('Content-Length', '4')])

This is case-insensitive.  It can support multiple values for a key,
though only if you use ``res.headers.add(key, value)`` or read them
with ``res.headers.getall(key)``.

Body & app_iter
---------------

The ``res.body`` attribute represents the entire body of the request
as a single string (not unicode, though you can set it to unicode if
you have a charset defined).  There is also a ``res.app_iter``
attribute that reprsents the body as an iterator.  WSGI applications
return these ``app_iter`` iterators instead of strings, and sometimes
it can be problematic to load the entire iterator at once (for
instance, if it returns the contents of a very large file).  Generally
it is not a problem, and often the iterator is something simple like a
one-item list containing a string with the entire body.

If you set the body then Content-Length will also be set, and an
``res.app_iter`` will be created for you.  If you set ``res.app_iter``
then Content-Length will be cleared, but it won't be set for you.

There is also a file-like object you can access, which will update the
app_iter in-place (turning the app_iter into a list if necessary):

.. code-block:: python

    >>> res = Response(content_type='text/plain', charset=None)
    >>> f = res.body_file
    >>> f.write('hey')
    >>> f.write(u'test')
    Traceback (most recent call last):
      . . .
    TypeError: You can only write unicode to Response if charset has been set
    >>> f.encoding
    >>> res.charset = 'utf8'
    >>> f.encoding
    'utf8'
    >>> f.write(u'test')
    >>> res.app_iter
    ['', 'hey', 'test']
    >>> res.body
    'heytest'

Header Getters
--------------

Like Request, HTTP response headers are also available as individual
properties.  These represent parsed forms of the headers.

Content-Type is a special case, as the type and the charset are
handled through two separate properties:

.. code-block:: python

    >>> res = Response()
    >>> res.content_type = 'text/html'
    >>> res.charset = 'utf8'
    >>> res.content_type
    'text/html'
    >>> res.headers['content-type']
    'text/html; charset=utf8'
    >>> res.content_type = 'application/atom+xml'
    >>> res.content_type_params
    {'charset': 'utf8'}
    >>> res.content_type_params = {'type': 'entry', 'charset': 'utf8'}
    >>> res.headers['content-type']
    'application/atom+xml; charset=utf8; type=entry'

Other headers:

.. code-block:: python

    >>> # Used with a redirect:
    >>> res.location = 'http://localhost/foo'

    >>> # Indicates that the server accepts Range requests:
    >>> res.accept_ranges = 'bytes'

    >>> # Used by caching proxies to tell the client how old the
    >>> # response is:
    >>> res.age = 120

    >>> # Show what methods the client can do; typically used in
    >>> # a 405 Method Not Allowed response:
    >>> res.allow = ['GET', 'PUT']

    >>> # Set the cache-control header:
    >>> res.cache_control.max_age = 360
    >>> res.cache_control.no_transform = True

    >>> # Tell the browser to treat the response as an attachment:
    >>> res.content_disposition = 'attachment; filename=foo.xml'

    >>> # Used if you had gzipped the body:
    >>> res.content_encoding = 'gzip'

    >>> # What language(s) are in the content:
    >>> res.content_language = ['en']

    >>> # Seldom used header that tells the client where the content
    >>> # is from:
    >>> res.content_location = 'http://localhost/foo'

    >>> # Seldom used header that gives a hash of the body:
    >>> res.content_md5 = 'big-hash'

    >>> # Means we are serving bytes 0-500 inclusive, out of 1000 bytes total:
    >>> # you can also use the range setter shown earlier
    >>> res.content_range = (0, 501, 1000)

    >>> # The length of the content; set automatically if you set
    >>> # res.body:
    >>> res.content_length = 4

    >>> # Used to indicate the current date as the server understands
    >>> # it:
    >>> res.date = datetime.now()

    >>> # The etag:
    >>> res.etag = 'opaque-token'
    >>> # You can generate it from the body too:
    >>> res.md5_etag()
    >>> res.etag
    '1B2M2Y8AsgTpgAmY7PhCfg'

    >>> # When this page should expire from a cache (Cache-Control
    >>> # often works better):
    >>> import time
    >>> res.expires = time.time() + 60*60 # 1 hour

    >>> # When this was last modified, of course:
    >>> res.last_modified = datetime(2007, 1, 1, 12, 0, tzinfo=UTC)

    >>> # Used with 503 Service Unavailable to hint the client when to
    >>> # try again:
    >>> res.retry_after = 160

    >>> # Indicate the server software:
    >>> res.server = 'WebOb/1.0'

    >>> # Give a list of headers that the cache should vary on:
    >>> res.vary = ['Cookie']

Note in each case you can general set the header to a string to avoid
any parsing, and set it to None to remove the header (or do something
like ``del res.vary``).

In the case of date-related headers you can set the value to a
``datetime`` instance (ideally with a UTC timezone), a time tuple, an
integer timestamp, or a properly-formatted string.

After setting all these headers, here's the result:

.. code-block:: python

    >>> for name, value in res.headerlist:
    ...     print '%s: %s' % (name, value)
    Content-Type: application/atom+xml; charset=utf8; type=entry
    Location: http://localhost/foo
    Accept-Ranges: bytes
    Age: 120
    Allow: GET, PUT
    Cache-Control: max-age=360, no-transform
    Content-Disposition: attachment; filename=foo.xml
    Content-Encoding: gzip
    Content-Language: en
    Content-Location: http://localhost/foo
    Content-MD5: big-hash
    Content-Range: bytes 0-500/1000
    Content-Length: 4
    Date: ... GMT
    ETag: ...
    Expires: ... GMT
    Last-Modified: Mon, 01 Jan 2007 12:00:00 GMT
    Retry-After: 160
    Server: WebOb/1.0
    Vary: Cookie

You can also set Cache-Control related attributes with
``req.cache_expires(seconds, **attrs)``, like:

.. code-block:: python

    >>> res = Response()
    >>> res.cache_expires(10)
    >>> res.headers['Cache-Control']
    'max-age=10'
    >>> res.cache_expires(0)
    >>> res.headers['Cache-Control']
    'max-age=0, must-revalidate, no-cache, no-store'
    >>> res.headers['Expires']
    '... GMT'

You can also use the `timedelta
<http://python.org/doc/current/lib/datetime-timedelta.html>`_
constants defined, e.g.:

.. code-block:: python

    >>> from webob import *
    >>> res = Response()
    >>> res.cache_expires(2*day+4*hour)
    >>> res.headers['Cache-Control']
    'max-age=187200'

Cookies
-------

Cookies (and the Set-Cookie header) are handled with a couple
methods.  Most importantly:

.. code-block:: python

    >>> res.set_cookie('key', 'value', max_age=360, path='/',
    ...                domain='example.org', secure=True)
    >>> res.headers['Set-Cookie']
    'key=value; Domain=example.org; Max-Age=360; Path=/; expires=... GMT; secure'
    >>> # To delete a cookie previously set in the client:
    >>> res.delete_cookie('bad_cookie')
    >>> res.headers['Set-Cookie']
    'bad_cookie=; Max-Age=0; Path=/; expires=... GMT'

The only other real method of note (note that this does *not* delete
the cookie from clients, only from the response object):

.. code-block:: python

    >>> res.unset_cookie('key')
    >>> res.unset_cookie('bad_cookie')
    >>> print res.headers.get('Set-Cookie')
    None

Binding a Request
-----------------

You can bind a request (or request WSGI environ) to the response
object.  This is available through ``res.request`` or
``res.environ``.  This is currently only used in setting
``res.location``, to make the location absolute if necessary.

Response as a WSGI application
------------------------------

A response is a WSGI application, in that you can do:

.. code-block:: python

    >>> req = Request.blank('/')
    >>> status, headers, app_iter = req.call_application(res)

A possible pattern for your application might be:

.. code-block:: python

    >>> def my_app(environ, start_response):
    ...     req = Request(environ)
    ...     res = Response()
    ...     res.content_type = 'text/plain'
    ...     parts = []
    ...     for name, value in sorted(req.environ.items()):
    ...         parts.append('%s: %r' % (name, value))
    ...     res.body = '\n'.join(parts)
    ...     return res(environ, start_response)
    >>> req = Request.blank('/')
    >>> res = req.get_response(my_app)
    >>> print res
    200 OK
    Content-Type: text/plain; charset=UTF-8
    Content-Length: ...
    <BLANKLINE>
    HTTP_HOST: 'localhost:80'
    PATH_INFO: '/'
    QUERY_STRING: ''
    REQUEST_METHOD: 'GET'
    SCRIPT_NAME: ''
    SERVER_NAME: 'localhost'
    SERVER_PORT: '80'
    SERVER_PROTOCOL: 'HTTP/1.0'
    wsgi.errors: <open file '<stderr>', mode 'w' at ...>
    wsgi.input: <...IO... object at ...>
    wsgi.multiprocess: False
    wsgi.multithread: False
    wsgi.run_once: False
    wsgi.url_scheme: 'http'
    wsgi.version: (1, 0)

Exceptions
==========

In addition to Request and Response objects, there are a set of Python
exceptions for different HTTP responses (3xx, 4xx, 5xx codes).

These provide a simple way to provide these non-200 response.  A very
simple body is provided.

.. code-block:: python

    >>> from webob.exc import *
    >>> exc = HTTPTemporaryRedirect(location='foo')
    >>> req = Request.blank('/path/to/something')
    >>> print str(req.get_response(exc)).strip()
    307 Temporary Redirect
    Location: http://localhost/path/to/foo
    Content-Length: 126
    Content-Type: text/plain; charset=UTF-8
    <BLANKLINE>
    307 Temporary Redirect
    <BLANKLINE>
    The resource has been moved to http://localhost/path/to/foo; you should be redirected automatically.

Note that only if there's an ``Accept: text/html`` header in the
request will an HTML response be given:

.. code-block:: python

    >>> req.accept += 'text/html'
    >>> print str(req.get_response(exc)).strip()
    307 Temporary Redirect
    Location: http://localhost/path/to/foo
    Content-Length: 270
    Content-Type: text/html; charset=UTF-8
    <BLANKLINE>
    <html>
     <head>
      <title>307 Temporary Redirect</title>
     </head>
     <body>
      <h1>307 Temporary Redirect</h1>
      The resource has been moved to <a href="http://localhost/path/to/foo">http://localhost/path/to/foo</a>;
    you should be redirected automatically.
    <BLANKLINE>
    <BLANKLINE>
     </body>
    </html>


This is taken from `paste.httpexceptions
<http://pythonpaste.org/modules/httpexceptions.html#module-paste.httpexceptions>`_, and if
you have Paste installed then these exceptions will be subclasses of
the Paste exceptions.


Conditional WSGI Application
----------------------------

The Response object can handle your conditional responses for you,
checking If-None-Match, If-Modified-Since, and Range/If-Range.

To enable this you must create the response like
``Response(conditional_response=True)``, or make a subclass like:

.. code-block:: python

    >>> class AppResponse(Response):
    ...     default_content_type = 'text/html'
    ...     default_conditional_response = True
    >>> res = AppResponse(body='0123456789',
    ...                   last_modified=datetime(2005, 1, 1, 12, 0, tzinfo=UTC))
    >>> req = Request.blank('/')
    >>> req.if_modified_since = datetime(2006, 1, 1, 12, 0, tzinfo=UTC)
    >>> req.get_response(res)
    <Response ... 304 Not Modified>
    >>> del req.if_modified_since
    >>> res.etag = 'opaque-tag'
    >>> req.if_none_match = 'opaque-tag'
    >>> req.get_response(res)
    <Response ... 304 Not Modified>

    >>> req.if_none_match = '*'
    >>> 'x' in req.if_none_match
    True
    >>> req.if_none_match = req.if_none_match
    >>> 'x' in req.if_none_match
    True
    >>> req.if_none_match = None
    >>> 'x' in req.if_none_match
    False
    >>> req.if_match = None
    >>> 'x' in req.if_match
    True
    >>> req.if_match = req.if_match
    >>> 'x' in req.if_match
    True
    >>> req.headers.get('If-Match')
    '*'

    >>> del req.if_none_match

    >>> req.range = (1, 5)
    >>> result = req.get_response(res)
    >>> result.headers['content-range']
    'bytes 1-4/10'
    >>> result.body
    '1234'
