1b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik"""
2b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThis module processes Python exceptions that relate to HTTP exceptions
3b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikby defining a set of exceptions, all subclasses of HTTPException.
4b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikEach exception, in addition to being a Python exception that can be
5b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikraised and caught, is also a WSGI application and ``webob.Response``
6b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikobject.
7b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
8b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThis module defines exceptions according to RFC 2068 [1]_ : codes with
9b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik100-300 are not really errors; 400's are client errors, and 500's are
10b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikserver errors.  According to the WSGI specification [2]_ , the application
11b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikcan call ``start_response`` more then once only under two conditions:
12b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik(a) the response has not yet been sent, or (b) if the second and
13b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craiksubsequent invocations of ``start_response`` have a valid ``exc_info``
14b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikargument obtained from ``sys.exc_info()``.  The WSGI specification then
15b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikrequires the server or gateway to handle the case where content has been
16b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craiksent and then an exception was encountered.
17b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
18b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikException
19b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  HTTPException
20b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    HTTPOk
21b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 200 - :class:`HTTPOk`
22b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 201 - :class:`HTTPCreated`
23b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 202 - :class:`HTTPAccepted`
24b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 203 - :class:`HTTPNonAuthoritativeInformation`
25b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 204 - :class:`HTTPNoContent`
26b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 205 - :class:`HTTPResetContent`
27b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 206 - :class:`HTTPPartialContent`
28b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    HTTPRedirection
29b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 300 - :class:`HTTPMultipleChoices`
30b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 301 - :class:`HTTPMovedPermanently`
31b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 302 - :class:`HTTPFound`
32b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 303 - :class:`HTTPSeeOther`
33b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 304 - :class:`HTTPNotModified`
34b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 305 - :class:`HTTPUseProxy`
35b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      * 307 - :class:`HTTPTemporaryRedirect`
36b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    HTTPError
37b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      HTTPClientError
38b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 400 - :class:`HTTPBadRequest`
39b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 401 - :class:`HTTPUnauthorized`
40b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 402 - :class:`HTTPPaymentRequired`
41b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 403 - :class:`HTTPForbidden`
42b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 404 - :class:`HTTPNotFound`
43b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 405 - :class:`HTTPMethodNotAllowed`
44b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 406 - :class:`HTTPNotAcceptable`
45b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 407 - :class:`HTTPProxyAuthenticationRequired`
46b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 408 - :class:`HTTPRequestTimeout`
47b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 409 - :class:`HTTPConflict`
48b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 410 - :class:`HTTPGone`
49b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 411 - :class:`HTTPLengthRequired`
50b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 412 - :class:`HTTPPreconditionFailed`
51b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 413 - :class:`HTTPRequestEntityTooLarge`
52b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 414 - :class:`HTTPRequestURITooLong`
53b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 415 - :class:`HTTPUnsupportedMediaType`
54b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 416 - :class:`HTTPRequestRangeNotSatisfiable`
55b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 417 - :class:`HTTPExpectationFailed`
56b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 422 - :class:`HTTPUnprocessableEntity`
57b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 423 - :class:`HTTPLocked`
58b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 424 - :class:`HTTPFailedDependency`
59b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 428 - :class:`HTTPPreconditionRequired`
60b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 429 - :class:`HTTPTooManyRequests`
61b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 431 - :class:`HTTPRequestHeaderFieldsTooLarge`
62b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 451 - :class:`HTTPUnavailableForLegalReasons`
63b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      HTTPServerError
64b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 500 - :class:`HTTPInternalServerError`
65b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 501 - :class:`HTTPNotImplemented`
66b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 502 - :class:`HTTPBadGateway`
67b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 503 - :class:`HTTPServiceUnavailable`
68b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 504 - :class:`HTTPGatewayTimeout`
69b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 505 - :class:`HTTPVersionNotSupported`
70b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        * 511 - :class:`HTTPNetworkAuthenticationRequired`
71b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
72b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikUsage notes
73b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik-----------
74b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
75b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThe HTTPException class is complicated by 4 factors:
76b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
77b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  1. The content given to the exception may either be plain-text or
78b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     as html-text.
79b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
80b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  2. The template may want to have string-substitutions taken from
81b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     the current ``environ`` or values from incoming headers. This
82b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     is especially troublesome due to case sensitivity.
83b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
84b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  3. The final output may either be text/plain or text/html
85b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     mime-type as requested by the client application.
86b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
87b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  4. Each exception has a default explanation, but those who
88b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     raise exceptions may want to provide additional detail.
89b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
90b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikSubclass attributes and call parameters are designed to provide an easier path
91b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikthrough the complications.
92b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
93b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikAttributes:
94b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
95b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``code``
96b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       the HTTP status code for the exception
97b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
98b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``title``
99b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       remainder of the status line (stuff after the code)
100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``explanation``
102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       a plain-text explanation of the error message that is
103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       not subject to environment or header substitutions;
104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       it is accessible in the template via %(explanation)s
105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``detail``
107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       a plain-text message customization that is not subject
108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       to environment or header substitutions; accessible in
109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       the template via %(detail)s
110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``body_template``
112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       a content fragment (in HTML) used for environment and
113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       header substitution; the default template includes both
114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       the explanation and further detail provided in the
115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik       message
116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikParameters:
118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``detail``
120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     a plain-text override of the default ``detail``
121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``headers``
123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     a list of (k,v) header pairs
124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``comment``
126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     a plain-text additional information which is
127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     usually stripped/hidden for end-users
128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik   ``body_template``
130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     a string.Template object containing a content fragment in HTML
131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik     that frames the explanation and further detail
132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikTo override the template (which is HTML content) or the plain-text
134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexplanation, one must subclass the given exception; or customize it
135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikafter it has been created.  This particular breakdown of a message
136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikinto explanation, detail and template allows both the creation of
137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikplain-text and html messages for various clients as well as
138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikerror-free substitution of environment variables and headers.
139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThe subclasses of :class:`~_HTTPMove`
142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik(:class:`~HTTPMultipleChoices`, :class:`~HTTPMovedPermanently`,
143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik:class:`~HTTPFound`, :class:`~HTTPSeeOther`, :class:`~HTTPUseProxy` and
144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik:class:`~HTTPTemporaryRedirect`) are redirections that require a ``Location``
145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfield. Reflecting this, these subclasses have two additional keyword arguments:
146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik``location`` and ``add_slash``.
147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikParameters:
149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ``location``
151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      to set the location immediately
152b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
153b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ``add_slash``
154b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      set to True to redirect to the same URL as the request, except with a
155b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      ``/`` appended
156b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
157b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikRelative URLs in the location will be resolved to absolute.
158b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
159b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikReferences:
160b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
161b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik.. [1] http://www.python.org/peps/pep-0333.html#error-handling
162b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik.. [2] http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5
163b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
164b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
165b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik"""
166b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
167b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom string import Template
168b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport re
169b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport sys
170b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
171b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.compat import (
172b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    class_types,
173b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    text_,
174b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    text_type,
175b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    urlparse,
176b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
177b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.request import Request
178b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.response import Response
179b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.util import (
180b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    html_escape,
181b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    warn_deprecation,
182b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    )
183b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
184b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craiktag_re = re.compile(r'<.*?>', re.S)
185b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikbr_re = re.compile(r'<br.*?>', re.I|re.S)
186b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikcomment_re = re.compile(r'<!--|-->')
187b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
188b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef no_escape(value):
189b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if value is None:
190b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return ''
191b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if not isinstance(value, text_type):
192b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if hasattr(value, '__unicode__'):
193b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            value = value.__unicode__()
194b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if isinstance(value, bytes):
195b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            value = text_(value, 'utf-8')
196b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        else:
197b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            value = text_type(value)
198b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return value
199b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
200b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef strip_tags(value):
201b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    value = value.replace('\n', ' ')
202b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    value = value.replace('\r', '')
203b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    value = br_re.sub('\n', value)
204b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    value = comment_re.sub('', value)
205b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    value = tag_re.sub('', value)
206b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return value
207b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
208b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPException(Exception):
209b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __init__(self, message, wsgi_response):
210b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        Exception.__init__(self, message)
211b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        self.wsgi_response = wsgi_response
212b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
213b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __call__(self, environ, start_response):
214b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return self.wsgi_response(environ, start_response)
215b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
216b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass WSGIHTTPException(Response, HTTPException):
217b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
218b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ## You should set in subclasses:
219b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # code = 200
220b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # title = 'OK'
221b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # explanation = 'why this happens'
222b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # body_template_obj = Template('response template')
223b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 500
224b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Internal Server Error'
225b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ''
226b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    body_template_obj = Template('''\
227b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${explanation}<br /><br />
228b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${detail}
229b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${html_comment}
230b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik''')
231b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
232b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    plain_template_obj = Template('''\
233b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${status}
234b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
235b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${body}''')
236b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
237b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    html_template_obj = Template('''\
238b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik<html>
239b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik <head>
240b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  <title>${status}</title>
241b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik </head>
242b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik <body>
243b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  <h1>${status}</h1>
244b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik  ${body}
245b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik </body>
246b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik</html>''')
247b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
248b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ## Set this to True for responses that should have no request body
249b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    empty_body = False
250b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
251b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __init__(self, detail=None, headers=None, comment=None,
252b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                 body_template=None, **kw):
253b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        Response.__init__(self,
254b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                          status='%s %s' % (self.code, self.title),
255b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                          **kw)
256b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        Exception.__init__(self, detail)
257b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if headers:
258b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            self.headers.extend(headers)
259b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        self.detail = detail
260b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        self.comment = comment
261b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if body_template is not None:
262b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            self.body_template = body_template
263b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            self.body_template_obj = Template(body_template)
264b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if self.empty_body:
265b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            del self.content_type
266b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            del self.content_length
267b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
268b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __str__(self):
269b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return self.detail or self.explanation
270b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
271b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def _make_body(self, environ, escape):
272b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        args = {
273b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            'explanation': escape(self.explanation),
274b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            'detail': escape(self.detail or ''),
275b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            'comment': escape(self.comment or ''),
276b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            }
277b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if self.comment:
278b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            args['html_comment'] = '<!-- %s -->' % escape(self.comment)
279b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        else:
280b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            args['html_comment'] = ''
281b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if WSGIHTTPException.body_template_obj is not self.body_template_obj:
282b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            # Custom template; add headers to args
283b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            for k, v in environ.items():
284b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                args[k] = escape(v)
285b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            for k, v in self.headers.items():
286b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                args[k.lower()] = escape(v)
287b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        t_obj = self.body_template_obj
288b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return t_obj.substitute(args)
289b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
290b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def plain_body(self, environ):
291b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        body = self._make_body(environ, no_escape)
292b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        body = strip_tags(body)
293b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return self.plain_template_obj.substitute(status=self.status,
294b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                                                  title=self.title,
295b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                                                  body=body)
296b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
297b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def html_body(self, environ):
298b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        body = self._make_body(environ, html_escape)
299b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return self.html_template_obj.substitute(status=self.status,
300b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                                                 body=body)
301b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
302b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def generate_response(self, environ, start_response):
303b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if self.content_length is not None:
304b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            del self.content_length
305b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        headerlist = list(self.headerlist)
306b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        accept = environ.get('HTTP_ACCEPT', '')
307b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if accept and 'html' in accept or '*/*' in accept:
308b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            content_type = 'text/html'
309b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            body = self.html_body(environ)
310b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        else:
311b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            content_type = 'text/plain'
312b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            body = self.plain_body(environ)
313b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        extra_kw = {}
314b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if isinstance(body, text_type):
315b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            extra_kw.update(charset='utf-8')
316b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        resp = Response(body,
317b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            status=self.status,
318b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            headerlist=headerlist,
319b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            content_type=content_type,
320b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            **extra_kw
321b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        )
322b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        resp.content_type = content_type
323b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return resp(environ, start_response)
324b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
325b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __call__(self, environ, start_response):
326b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        is_head = environ['REQUEST_METHOD'] == 'HEAD'
327b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if self.body or self.empty_body or is_head:
328b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            app_iter = Response.__call__(self, environ, start_response)
329b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        else:
330b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            app_iter = self.generate_response(environ, start_response)
331b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if is_head:
332b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            app_iter = []
333b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return app_iter
334b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
335b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    @property
336b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def wsgi_response(self):
337b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return self
338b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
339b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
340b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
341b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPError(WSGIHTTPException):
342b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
343b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    base class for status codes in the 400's and 500's
344b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
345b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This is an exception which indicates that an error has occurred,
346b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    and that any work in progress should not be committed.  These are
347b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    typically results in the 400's and 500's.
348b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
349b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
350b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPRedirection(WSGIHTTPException):
351b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
352b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    base class for 300's status code (redirections)
353b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
354b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This is an abstract base class for 3xx redirection.  It indicates
355b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    that further action needs to be taken by the user agent in order
356b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    to fulfill the request.  It does not necessarly signal an error
357b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    condition.
358b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
359b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
360b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPOk(WSGIHTTPException):
361b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
362b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Base class for the 200's status code (successful responses)
363b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
364b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 200, title: OK
365b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
366b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 200
367b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'OK'
368b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
369b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
370b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik## 2xx success
371b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
372b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
373b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPCreated(HTTPOk):
374b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
375b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPOk`
376b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
377b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that request has been fulfilled and resulted in a new
378b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    resource being created.
379b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
380b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 201, title: Created
381b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
382b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 201
383b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Created'
384b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
385b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPAccepted(HTTPOk):
386b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
387b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPOk`
388b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
389b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the request has been accepted for processing, but the
390b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    processing has not been completed.
391b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
392b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 202, title: Accepted
393b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
394b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 202
395b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Accepted'
396b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = 'The request is accepted for processing.'
397b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
398b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPNonAuthoritativeInformation(HTTPOk):
399b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
400b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPOk`
401b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
402b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the returned metainformation in the entity-header is
403b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    not the definitive set as available from the origin server, but is
404b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    gathered from a local or a third-party copy.
405b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
406b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 203, title: Non-Authoritative Information
407b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
408b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 203
409b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Non-Authoritative Information'
410b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
411b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPNoContent(HTTPOk):
412b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
413b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPOk`
414b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
415b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server has fulfilled the request but does
416b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    not need to return an entity-body, and might want to return updated
417b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    metainformation.
418b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
419b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 204, title: No Content
420b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
421b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 204
422b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'No Content'
423b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    empty_body = True
424b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
425b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPResetContent(HTTPOk):
426b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
427b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPOk`
428b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
429b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the the server has fulfilled the request and
430b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    the user agent SHOULD reset the document view which caused the
431b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request to be sent.
432b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
433b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 205, title: Reset Content
434b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
435b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 205
436b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Reset Content'
437b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    empty_body = True
438b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
439b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPPartialContent(HTTPOk):
440b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
441b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPOk`
442b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
443b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server has fulfilled the partial GET
444b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request for the resource.
445b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
446b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 206, title: Partial Content
447b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
448b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 206
449b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Partial Content'
450b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
451b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
452b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik## 3xx redirection
453b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
454b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
455b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass _HTTPMove(HTTPRedirection):
456b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
457b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    redirections which require a Location field
458b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
459b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Since a 'Location' header is a required attribute of 301, 302, 303,
460b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    305 and 307 (but not 304), this base class provides the mechanics to
461b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    make this easy.
462b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
463b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    You can provide a location keyword argument to set the location
464b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    immediately.  You may also give ``add_slash=True`` if you want to
465b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    redirect to the same URL as the request, except with a ``/`` added
466b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    to the end.
467b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
468b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Relative URLs in the location will be resolved to absolute.
469b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
470b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = 'The resource has been moved to'
471b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    body_template_obj = Template('''\
472b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${explanation} <a href="${location}">${location}</a>;
473b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikyou should be redirected automatically.
474b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${detail}
475b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${html_comment}''')
476b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
477b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __init__(self, detail=None, headers=None, comment=None,
478b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                 body_template=None, location=None, add_slash=False):
479b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        super(_HTTPMove, self).__init__(
480b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            detail=detail, headers=headers, comment=comment,
481b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            body_template=body_template)
482b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if location is not None:
483b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            self.location = location
484b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if add_slash:
485b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                raise TypeError(
486b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    "You can only provide one of the arguments location "
487b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    "and add_slash")
488b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        self.add_slash = add_slash
489b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
490b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __call__(self, environ, start_response):
491b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        req = Request(environ)
492b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if self.add_slash:
493b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            url = req.path_url
494b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            url += '/'
495b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            if req.environ.get('QUERY_STRING'):
496b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                url += '?' + req.environ['QUERY_STRING']
497b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            self.location = url
498b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        self.location = urlparse.urljoin(req.path_url, self.location)
499b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return super(_HTTPMove, self).__call__(
500b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            environ, start_response)
501b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
502b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPMultipleChoices(_HTTPMove):
503b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
504b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~_HTTPMove`
505b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
506b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the requested resource corresponds to any one
507b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    of a set of representations, each with its own specific location,
508b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    and agent-driven negotiation information is being provided so that
509b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    the user can select a preferred representation and redirect its
510b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request to that location.
511b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
512b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 300, title: Multiple Choices
513b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
514b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 300
515b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Multiple Choices'
516b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
517b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPMovedPermanently(_HTTPMove):
518b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
519b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~_HTTPMove`
520b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
521b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the requested resource has been assigned a new
522b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    permanent URI and any future references to this resource SHOULD use
523b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    one of the returned URIs.
524b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
525b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 301, title: Moved Permanently
526b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
527b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 301
528b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Moved Permanently'
529b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
530b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPFound(_HTTPMove):
531b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
532b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~_HTTPMove`
533b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
534b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the requested resource resides temporarily under
535b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    a different URI.
536b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
537b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 302, title: Found
538b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
539b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 302
540b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Found'
541b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = 'The resource was found at'
542b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
543b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# This one is safe after a POST (the redirected location will be
544b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# retrieved with GET):
545b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPSeeOther(_HTTPMove):
546b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
547b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~_HTTPMove`
548b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
549b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the response to the request can be found under
550b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    a different URI and SHOULD be retrieved using a GET method on that
551b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    resource.
552b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
553b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 303, title: See Other
554b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
555b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 303
556b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'See Other'
557b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
558b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPNotModified(HTTPRedirection):
559b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
560b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPRedirection`
561b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
562b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that if the client has performed a conditional GET
563b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request and access is allowed, but the document has not been
564b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    modified, the server SHOULD respond with this status code.
565b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
566b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 304, title: Not Modified
567b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
568b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # TODO: this should include a date or etag header
569b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 304
570b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Not Modified'
571b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    empty_body = True
572b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
573b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPUseProxy(_HTTPMove):
574b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
575b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~_HTTPMove`
576b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
577b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the requested resource MUST be accessed through
578b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    the proxy given by the Location field.
579b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
580b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 305, title: Use Proxy
581b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
582b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # Not a move, but looks a little like one
583b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 305
584b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Use Proxy'
585b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = (
586b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'The resource must be accessed through a proxy located at')
587b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
588b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPTemporaryRedirect(_HTTPMove):
589b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
590b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~_HTTPMove`
591b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
592b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the requested resource resides temporarily
593b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    under a different URI.
594b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
595b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 307, title: Temporary Redirect
596b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
597b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 307
598b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Temporary Redirect'
599b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
600b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
601b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik## 4xx client error
602b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
603b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
604b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPClientError(HTTPError):
605b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
606b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    base class for the 400's, where the client is in error
607b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
608b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This is an error condition in which the client is presumed to be
609b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    in-error.  This is an expected problem, and thus is not considered
610b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    a bug.  A server-side traceback is not warranted.  Unless specialized,
611b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    this is a '400 Bad Request'
612b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
613b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 400, title: Bad Request
614b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
615b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 400
616b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Bad Request'
617b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The server could not comply with the request since\r\n'
618b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                   'it is either malformed or otherwise incorrect.\r\n')
619b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
620b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPBadRequest(HTTPClientError):
621b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    pass
622b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
623b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPUnauthorized(HTTPClientError):
624b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
625b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
626b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
627b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the request requires user authentication.
628b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
629b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 401, title: Unauthorized
630b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
631b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 401
632b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Unauthorized'
633b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = (
634b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'This server could not verify that you are authorized to\r\n'
635b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'access the document you requested.  Either you supplied the\r\n'
636b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'wrong credentials (e.g., bad password), or your browser\r\n'
637b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'does not understand how to supply the credentials required.\r\n')
638b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
639b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPPaymentRequired(HTTPClientError):
640b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
641b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
642b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
643b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 402, title: Payment Required
644b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
645b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 402
646b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Payment Required'
647b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Access was denied for financial reasons.')
648b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
649b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPForbidden(HTTPClientError):
650b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
651b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
652b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
653b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server understood the request, but is
654b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    refusing to fulfill it.
655b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
656b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 403, title: Forbidden
657b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
658b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 403
659b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Forbidden'
660b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Access was denied to this resource.')
661b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
662b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPNotFound(HTTPClientError):
663b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
664b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
665b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
666b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server did not find anything matching the
667b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Request-URI.
668b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
669b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 404, title: Not Found
670b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
671b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 404
672b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Not Found'
673b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The resource could not be found.')
674b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
675b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPMethodNotAllowed(HTTPClientError):
676b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
677b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
678b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
679b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the method specified in the Request-Line is
680b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    not allowed for the resource identified by the Request-URI.
681b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
682b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 405, title: Method Not Allowed
683b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
684b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 405
685b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Method Not Allowed'
686b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # override template since we need an environment variable
687b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    body_template_obj = Template('''\
688b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThe method ${REQUEST_METHOD} is not allowed for this resource. <br /><br />
689b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${detail}''')
690b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
691b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPNotAcceptable(HTTPClientError):
692b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
693b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
694b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
695b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates the resource identified by the request is only
696b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    capable of generating response entities which have content
697b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    characteristics not acceptable according to the accept headers
698b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    sent in the request.
699b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
700b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 406, title: Not Acceptable
701b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
702b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 406
703b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Not Acceptable'
704b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # override template since we need an environment variable
705b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    template = Template('''\
706b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThe resource could not be generated that was acceptable to your browser
707b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik(content of type ${HTTP_ACCEPT}. <br /><br />
708b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${detail}''')
709b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
710b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPProxyAuthenticationRequired(HTTPClientError):
711b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
712b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
713b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
714b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This is similar to 401, but indicates that the client must first
715b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    authenticate itself with the proxy.
716b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
717b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 407, title: Proxy Authentication Required
718b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
719b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 407
720b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Proxy Authentication Required'
721b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Authentication with a local proxy is needed.')
722b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
723b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPRequestTimeout(HTTPClientError):
724b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
725b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
726b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
727b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the client did not produce a request within
728b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    the time that the server was prepared to wait.
729b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
730b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 408, title: Request Timeout
731b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
732b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 408
733b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Request Timeout'
734b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The server has waited too long for the request to '
735b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                   'be sent by the client.')
736b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
737b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPConflict(HTTPClientError):
738b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
739b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
740b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
741b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the request could not be completed due to a
742b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    conflict with the current state of the resource.
743b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
744b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 409, title: Conflict
745b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
746b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 409
747b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Conflict'
748b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('There was a conflict when trying to complete '
749b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                   'your request.')
750b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
751b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPGone(HTTPClientError):
752b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
753b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
754b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
755b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the requested resource is no longer available
756b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    at the server and no forwarding address is known.
757b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
758b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 410, title: Gone
759b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
760b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 410
761b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Gone'
762b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('This resource is no longer available.  No forwarding '
763b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                   'address is given.')
764b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
765b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPLengthRequired(HTTPClientError):
766b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
767b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
768b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
769b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the the server refuses to accept the request
770b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    without a defined Content-Length.
771b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
772b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 411, title: Length Required
773b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
774b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 411
775b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Length Required'
776b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Content-Length header required.')
777b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
778b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPPreconditionFailed(HTTPClientError):
779b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
780b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
781b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
782b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the precondition given in one or more of the
783b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request-header fields evaluated to false when it was tested on the
784b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    server.
785b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
786b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 412, title: Precondition Failed
787b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
788b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 412
789b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Precondition Failed'
790b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Request precondition failed.')
791b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
792b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPRequestEntityTooLarge(HTTPClientError):
793b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
794b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
795b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
796b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server is refusing to process a request
797b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    because the request entity is larger than the server is willing or
798b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    able to process.
799b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
800b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 413, title: Request Entity Too Large
801b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
802b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 413
803b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Request Entity Too Large'
804b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The body of your request was too large for this server.')
805b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
806b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPRequestURITooLong(HTTPClientError):
807b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
808b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
809b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
810b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server is refusing to service the request
811b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    because the Request-URI is longer than the server is willing to
812b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    interpret.
813b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
814b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 414, title: Request-URI Too Long
815b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
816b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 414
817b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Request-URI Too Long'
818b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The request URI was too long for this server.')
819b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
820b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPUnsupportedMediaType(HTTPClientError):
821b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
822b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
823b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
824b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server is refusing to service the request
825b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    because the entity of the request is in a format not supported by
826b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    the requested resource for the requested method.
827b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
828b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 415, title: Unsupported Media Type
829b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
830b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 415
831b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Unsupported Media Type'
832b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # override template since we need an environment variable
833b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    template_obj = Template('''\
834b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThe request media type ${CONTENT_TYPE} is not supported by this server.
835b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik<br /><br />
836b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${detail}''')
837b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
838b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPRequestRangeNotSatisfiable(HTTPClientError):
839b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
840b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
841b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
842b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    The server SHOULD return a response with this status code if a
843b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request included a Range request-header field, and none of the
844b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    range-specifier values in this field overlap the current extent
845b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    of the selected resource, and the request did not include an
846b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    If-Range request-header field.
847b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
848b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 416, title: Request Range Not Satisfiable
849b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
850b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 416
851b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Request Range Not Satisfiable'
852b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The Range requested is not available.')
853b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
854b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPExpectationFailed(HTTPClientError):
855b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
856b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
857b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
858b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indidcates that the expectation given in an Expect
859b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request-header field could not be met by this server.
860b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
861b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 417, title: Expectation Failed
862b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
863b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 417
864b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Expectation Failed'
865b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Expectation failed.')
866b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
867b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPUnprocessableEntity(HTTPClientError):
868b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
869b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
870b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
871b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server is unable to process the contained
872b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    instructions.
873b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
874b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 422, title: Unprocessable Entity
875b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
876b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ## Note: from WebDAV
877b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 422
878b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Unprocessable Entity'
879b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = 'Unable to process the contained instructions'
880b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
881b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPLocked(HTTPClientError):
882b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
883b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
884b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
885b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the resource is locked.
886b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
887b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 423, title: Locked
888b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
889b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ## Note: from WebDAV
890b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 423
891b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Locked'
892b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The resource is locked')
893b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
894b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPFailedDependency(HTTPClientError):
895b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
896b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
897b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
898b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the method could not be performed because the
899b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    requested action depended on another action and that action failed.
900b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
901b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 424, title: Failed Dependency
902b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
903b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ## Note: from WebDAV
904b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 424
905b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Failed Dependency'
906b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = (
907b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'The method could not be performed because the requested '
908b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'action dependended on another action and that action failed')
909b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
910b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPPreconditionRequired(HTTPClientError):
911b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
912b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
913b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
914b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the origin server requires the request to be
915b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    conditional.  From RFC 6585, "Additional HTTP Status Codes".
916b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
917b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 428, title: Precondition Required
918b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
919b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 428
920b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Precondition Required'
921b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('This request is required to be conditional')
922b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
923b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPTooManyRequests(HTTPClientError):
924b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
925b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
926b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
927b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the client has sent too many requests in a
928b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    given amount of time.  Useful for rate limiting.
929b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
930b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    From RFC 6585, "Additional HTTP Status Codes".
931b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
932b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 429, title: Too Many Requests
933b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
934b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 429
935b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Too Many Requests'
936b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = (
937b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'The client has sent too many requests in a given amount of time')
938b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
939b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPRequestHeaderFieldsTooLarge(HTTPClientError):
940b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
941b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
942b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
943b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server is unwilling to process the request
944b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    because its header fields are too large. The request may be resubmitted
945b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    after reducing the size of the request header fields.
946b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
947b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    From RFC 6585, "Additional HTTP Status Codes".
948b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
949b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 431, title: Request Header Fields Too Large
950b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
951b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 431
952b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Request Header Fields Too Large'
953b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = (
954b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'The request header fields were too large')
955b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
956b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPUnavailableForLegalReasons(HTTPClientError):
957b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
958b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPClientError`
959b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
960b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server is unable to process the request
961b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    because of legal reasons, e.g. censorship or government-mandated
962b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    blocked access.
963b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
964b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    From the draft "A New HTTP Status Code for Legally-restricted Resources"
965b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    by Tim Bray:
966b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
967b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    http://tools.ietf.org/html/draft-tbray-http-legally-restricted-status-00
968b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
969b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 451, title: Unavailable For Legal Reasons
970b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
971b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 451
972b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Unavailable For Legal Reasons'
973b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The resource is not available due to legal reasons.')
974b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
975b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
976b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik## 5xx Server Error
977b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik############################################################
978b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#  Response status codes beginning with the digit "5" indicate cases in
979b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#  which the server is aware that it has erred or is incapable of
980b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#  performing the request. Except when responding to a HEAD request, the
981b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#  server SHOULD include an entity containing an explanation of the error
982b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#  situation, and whether it is a temporary or permanent condition. User
983b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#  agents SHOULD display any included entity to the user. These response
984b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik#  codes are applicable to any request method.
985b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
986b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPServerError(HTTPError):
987b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
988b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    base class for the 500's, where the server is in-error
989b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
990b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This is an error condition in which the server is presumed to be
991b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    in-error.  This is usually unexpected, and thus requires a traceback;
992b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    ideally, opening a support ticket for the customer. Unless specialized,
993b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    this is a '500 Internal Server Error'
994b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
995b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 500
996b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Internal Server Error'
997b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = (
998b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      'The server has either erred or is incapable of performing\r\n'
999b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik      'the requested operation.\r\n')
1000b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1001b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPInternalServerError(HTTPServerError):
1002b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    pass
1003b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1004b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPNotImplemented(HTTPServerError):
1005b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1006b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPServerError`
1007b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1008b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server does not support the functionality
1009b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    required to fulfill the request.
1010b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1011b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 501, title: Not Implemented
1012b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1013b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 501
1014b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Not Implemented'
1015b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    template = Template('''
1016b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikThe request method ${REQUEST_METHOD} is not implemented for this server. <br /><br />
1017b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik${detail}''')
1018b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1019b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPBadGateway(HTTPServerError):
1020b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1021b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPServerError`
1022b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1023b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server, while acting as a gateway or proxy,
1024b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    received an invalid response from the upstream server it accessed
1025b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    in attempting to fulfill the request.
1026b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1027b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 502, title: Bad Gateway
1028b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1029b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 502
1030b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Bad Gateway'
1031b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Bad gateway.')
1032b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1033b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPServiceUnavailable(HTTPServerError):
1034b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1035b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPServerError`
1036b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1037b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server is currently unable to handle the
1038b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    request due to a temporary overloading or maintenance of the server.
1039b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1040b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 503, title: Service Unavailable
1041b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1042b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 503
1043b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Service Unavailable'
1044b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The server is currently unavailable. '
1045b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                   'Please try again at a later time.')
1046b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1047b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPGatewayTimeout(HTTPServerError):
1048b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1049b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPServerError`
1050b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1051b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server, while acting as a gateway or proxy,
1052b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    did not receive a timely response from the upstream server specified
1053b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    by the URI (e.g. HTTP, FTP, LDAP) or some other auxiliary server
1054b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    (e.g. DNS) it needed to access in attempting to complete the request.
1055b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1056b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 504, title: Gateway Timeout
1057b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1058b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 504
1059b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Gateway Timeout'
1060b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The gateway has timed out.')
1061b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1062b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPVersionNotSupported(HTTPServerError):
1063b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1064b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPServerError`
1065b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1066b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server does not support, or refuses to
1067b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    support, the HTTP protocol version that was used in the request
1068b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    message.
1069b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1070b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 505, title: HTTP Version Not Supported
1071b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1072b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 505
1073b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'HTTP Version Not Supported'
1074b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('The HTTP version is not supported.')
1075b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1076b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPInsufficientStorage(HTTPServerError):
1077b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1078b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPServerError`
1079b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1080b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the server does not have enough space to save
1081b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    the resource.
1082b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1083b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 507, title: Insufficient Storage
1084b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1085b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 507
1086b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Insufficient Storage'
1087b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('There was not enough space to save the resource')
1088b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1089b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPNetworkAuthenticationRequired(HTTPServerError):
1090b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1091b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    subclass of :class:`~HTTPServerError`
1092b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1093b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This indicates that the client needs to authenticate to gain
1094b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    network access.  From RFC 6585, "Additional HTTP Status Codes".
1095b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1096b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code: 511, title: Network Authentication Required
1097b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1098b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    code = 511
1099b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    title = 'Network Authentication Required'
1100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    explanation = ('Network authentication is required')
1101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass HTTPExceptionMiddleware(object):
1103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Middleware that catches exceptions in the sub-application.  This
1105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    does not catch exceptions in the app_iter; only during the initial
1106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    calling of the application.
1107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    This should be put *very close* to applications that might raise
1109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    these exceptions.  This should not be applied globally; letting
1110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    *expected* exceptions raise through the WSGI stack is dangerous.
1111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    """
1112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __init__(self, application):
1114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        self.application = application
1115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    def __call__(self, environ, start_response):
1116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        try:
1117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return self.application(environ, start_response)
1118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        except HTTPException:
1119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            parent_exc_info = sys.exc_info()
1120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            def repl_start_response(status, headers, exc_info=None):
1121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                if exc_info is None:
1122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                    exc_info = parent_exc_info
1123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                return start_response(status, headers, exc_info)
1124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return parent_exc_info[1](environ, repl_start_response)
1125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craiktry:
1127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    from paste import httpexceptions
1128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexcept ImportError:   # pragma: no cover
1129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    # Without Paste we don't need to do this fixup
1130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    pass
1131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikelse: # pragma: no cover
1132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    for name in dir(httpexceptions):
1133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        obj = globals().get(name)
1134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if (obj and isinstance(obj, type) and issubclass(obj, HTTPException)
1135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            and obj is not HTTPException
1136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            and obj is not WSGIHTTPException):
1137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            obj.__bases__ = obj.__bases__ + (getattr(httpexceptions, name),)
1138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    del name, obj, httpexceptions
1139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
1140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik__all__ = ['HTTPExceptionMiddleware', 'status_map']
1141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikstatus_map={}
1142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfor name, value in list(globals().items()):
1143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if (isinstance(value, (type, class_types)) and
1144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        issubclass(value, HTTPException)
1145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        and not name.startswith('_')):
1146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        __all__.append(name)
1147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if getattr(value, 'code', None):
1148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            status_map[value.code]=value
1149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if hasattr(value, 'explanation'):
1150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            value.explanation = ' '.join(value.explanation.strip().split())
1151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdel name, value
1152