1 WebOb 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 28 Status & License 29 ================ 30 31 WebOb is an extraction and refinement of pieces from `Paste 32 <http://pythonpaste.org/>`_. It is under active development. 33 Discussion 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 36 written by `Ian Bicking <http://ianbicking.org/>`_, and is being maintained 37 by the `Pylons Project <http://www.pylonsproject.org/>`. 38 39 WebOb is released under an `MIT-style license <license.html>`_. 40 41 WebOb development happens on `GitHub <https://github.com/Pylons/webob>`_. 42 Development version is installable via `easy_install 43 webob==dev <https://github.com/Pylons/webob/zipball/master>`__. You 44 can clone the source code with:: 45 46 $ git clone https://github.com/Pylons/webob.git 47 48 Introduction 49 ============ 50 51 WebOb provides objects for HTTP requests and responses. Specifically 52 it does this by wrapping the `WSGI <http://wsgi.org>`_ request 53 environment and response status/headers/app_iter(body). 54 55 The request and response objects provide many conveniences for parsing 56 HTTP request and forming HTTP responses. Both objects are read/write: 57 as a result, WebOb is also a nice way to create HTTP requests and 58 parse HTTP responses; however, we won't cover that use case in this 59 document. The `reference documentation <reference.html>`_ shows many 60 examples of creating requests. 61 62 Request 63 ======= 64 65 The request object is a wrapper around the `WSGI environ dictionary 66 <http://www.python.org/dev/peps/pep-0333/#environ-variables>`_. This 67 dictionary contains keys for each header, keys that describe the 68 request (including the path and query string), a file-like object for 69 the request body, and a variety of custom keys. You can always access 70 the environ with ``req.environ``. 71 72 Some of the most important/interesting attributes of a request 73 object: 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 113 Also, for standard HTTP request headers there are usually attributes, 114 for 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 117 instance, ``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 122 URLs 123 ---- 124 125 In addition to these attributes, there are several ways to get the URL 126 of the request. I'll show various values for an example URL 127 ``http://localhost/app-root/doc?article_id=10``, where the application 128 is 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 145 Methods 146 ------- 147 148 There are several methods in :class:`webob.Request` but only a few you'll use 149 often: 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 164 Unicode 165 ------- 166 167 Many of the properties in the request object will return unicode 168 values if the request encoding/charset is provided. The client *can* 169 indicate the charset with something like ``Content-Type: 170 application/x-www-form-urlencoded; charset=utf8``, but browsers seldom 171 set this. You can set the charset with ``req.charset = 'utf8'``, or 172 during instantiation with ``Request(environ, charset='utf8')``. If 173 you subclass ``Request`` you can also set ``charset`` as a class-level 174 attribute. 175 176 If it is set, then ``req.POST``, ``req.GET``, ``req.params``, and 177 ``req.cookies`` will contain unicode strings. Each has a 178 corresponding ``req.str_*`` (like ``req.str_POST``) that is always 179 ``str`` and never unicode. 180 181 Response 182 ======== 183 184 The response object looks a lot like the request object, though with 185 some differences. The request object wraps a single ``environ`` 186 object; the response object has three fundamental parts (based on 187 WSGI): 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 207 Everything else in the object derives from this underlying state. 208 Here'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 248 Headers 249 ------- 250 251 Like the request, most HTTP response headers are available as 252 properties. These are parsed, so you can do things like 253 ``response.last_modified = os.path.getmtime(filename)``. 254 255 The details are available in the `extracted Response documentation 256 <class-webob.Response.html>`_. 257 258 Instantiating the Response 259 -------------------------- 260 261 Of course most of the time you just want to *make* a response. 262 Generally any attribute of the response can be passed in as a keyword 263 argument to the class; e.g.: 264 265 .. code-block:: python 266 267 response = Response(body='hello world!', content_type='text/plain') 268 269 The status defaults to ``'200 OK'``. The content_type does not 270 default to anything, though if you subclass ``Response`` and set 271 ``default_content_type`` you can override this behavior. 272 273 Exceptions 274 ========== 275 276 To facilitate error responses like 404 Not Found, the module 277 ``webob.exc`` contains classes for each kind of error response. These 278 include boring but appropriate error bodies. 279 280 Each class is named ``webob.exc.HTTP*``, where ``*`` is the reason for 281 the error. For instance, ``webob.exc.HTTPNotFound``. It subclasses 282 ``Response``, so you can manipulate the instances in the same way. A 283 typical 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 291 You 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 301 The exceptions are still WSGI applications, but you cannot set 302 attributes like ``content_type``, ``charset``, etc. on these exception 303 objects. 304 305 Multidict 306 ========= 307 308 Several parts of WebOb use a "multidict"; this is a dictionary where a 309 key can have multiple values. The quintessential example is a query 310 string like ``?pref=red&pref=blue``; the ``pref`` variable has two 311 values: ``red`` and ``blue``. 312 313 In a multidict, when you do ``request.GET['pref']`` you'll get back 314 only ``'blue'`` (the last value of ``pref``). Sometimes returning a 315 string, and sometimes returning a list, is the cause of frequent 316 exceptions. If you want *all* the values back, use 317 ``request.GET.getall('pref')``. If you want to be sure there is *one 318 and only one* value, use ``request.GET.getone('pref')``, which will 319 raise an exception if there is zero or more than one value for 320 ``pref``. 321 322 When you use operations like ``request.GET.items()`` you'll get back 323 something like ``[('pref', 'red'), ('pref', 'blue')]``. All the 324 key/value pairs will show up. Similarly ``request.GET.keys()`` 325 returns ``['pref', 'pref']``. Multidict is a view on a list of 326 tuples; all the keys are ordered, and all the values are ordered. 327 328 Example 329 ======= 330 331 The `file-serving example <file-example.html>`_ shows how to do more 332 advanced HTTP techniques, while the `comment middleware example 333 <comment-example.html>`_ shows middleware. For applications it's more 334 reasonable 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