Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/pyramid/httpexceptions.py : 71%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2HTTP Exceptions
3---------------
5This module contains Pyramid HTTP exception classes. Each class relates to a
6single HTTP status code. Each class is a subclass of the
7:class:`~HTTPException`. Each exception class is also a :term:`response`
8object.
10Each exception class has a status code according to :rfc:`2068` or :rfc:`7538`:
11codes with 100-300 are not really errors; 400s are client errors,
12and 500s are server errors.
14Exception
15 HTTPException
16 HTTPSuccessful
17 * 200 - HTTPOk
18 * 201 - HTTPCreated
19 * 202 - HTTPAccepted
20 * 203 - HTTPNonAuthoritativeInformation
21 * 204 - HTTPNoContent
22 * 205 - HTTPResetContent
23 * 206 - HTTPPartialContent
24 HTTPRedirection
25 * 300 - HTTPMultipleChoices
26 * 301 - HTTPMovedPermanently
27 * 302 - HTTPFound
28 * 303 - HTTPSeeOther
29 * 304 - HTTPNotModified
30 * 305 - HTTPUseProxy
31 * 307 - HTTPTemporaryRedirect
32 * 308 - HTTPPermanentRedirect
33 HTTPError
34 HTTPClientError
35 * 400 - HTTPBadRequest
36 * 401 - HTTPUnauthorized
37 * 402 - HTTPPaymentRequired
38 * 403 - HTTPForbidden
39 * 404 - HTTPNotFound
40 * 405 - HTTPMethodNotAllowed
41 * 406 - HTTPNotAcceptable
42 * 407 - HTTPProxyAuthenticationRequired
43 * 408 - HTTPRequestTimeout
44 * 409 - HTTPConflict
45 * 410 - HTTPGone
46 * 411 - HTTPLengthRequired
47 * 412 - HTTPPreconditionFailed
48 * 413 - HTTPRequestEntityTooLarge
49 * 414 - HTTPRequestURITooLong
50 * 415 - HTTPUnsupportedMediaType
51 * 416 - HTTPRequestRangeNotSatisfiable
52 * 417 - HTTPExpectationFailed
53 * 422 - HTTPUnprocessableEntity
54 * 423 - HTTPLocked
55 * 424 - HTTPFailedDependency
56 * 428 - HTTPPreconditionRequired
57 * 429 - HTTPTooManyRequests
58 * 431 - HTTPRequestHeaderFieldsTooLarge
59 HTTPServerError
60 * 500 - HTTPInternalServerError
61 * 501 - HTTPNotImplemented
62 * 502 - HTTPBadGateway
63 * 503 - HTTPServiceUnavailable
64 * 504 - HTTPGatewayTimeout
65 * 505 - HTTPVersionNotSupported
66 * 507 - HTTPInsufficientStorage
68HTTP exceptions are also :term:`response` objects, thus they accept most of
69the same parameters that can be passed to a regular
70:class:`~pyramid.response.Response`. Each HTTP exception also has the
71following attributes:
73 ``code``
74 the HTTP status code for the exception
76 ``title``
77 remainder of the status line (stuff after the code)
79 ``explanation``
80 a plain-text explanation of the error message that is
81 not subject to environment or header substitutions;
82 it is accessible in the template via ${explanation}
84 ``detail``
85 a plain-text message customization that is not subject
86 to environment or header substitutions; accessible in
87 the template via ${detail}
89 ``body_template``
90 a ``String.template``-format content fragment used for environment
91 and header substitution; the default template includes both
92 the explanation and further detail provided in the
93 message.
95Each HTTP exception accepts the following parameters, any others will
96be forwarded to its :class:`~pyramid.response.Response` superclass:
98 ``detail``
99 a plain-text override of the default ``detail``
101 ``headers``
102 a list of (k,v) header pairs, or a dict, to be added to the
103 response; use the content_type='application/json' kwarg and other
104 similar kwargs to to change properties of the response supported by the
105 :class:`pyramid.response.Response` superclass
107 ``comment``
108 a plain-text additional information which is
109 usually stripped/hidden for end-users
111 ``body_template``
112 a ``string.Template`` object containing a content fragment in HTML
113 that frames the explanation and further detail
115 ``body``
116 a string that will override the ``body_template`` and be used as the
117 body of the response.
119Substitution of response headers into template values is always performed.
120Substitution of WSGI environment values is performed if a ``request`` is
121passed to the exception's constructor.
123The subclasses of :class:`~_HTTPMove`
124(:class:`~HTTPMultipleChoices`, :class:`~HTTPMovedPermanently`,
125:class:`~HTTPFound`, :class:`~HTTPSeeOther`, :class:`~HTTPUseProxy`,
126:class:`~HTTPTemporaryRedirect`, and :class: `~HTTPPermanentRedirect) are
127redirections that require a ``Location`` field. Reflecting this, these
128subclasses have one additional keyword argument: ``location``,
129which indicates the location to which to redirect.
130"""
131import json
133from string import Template
135from zope.interface import implementer
137from webob import html_escape as _html_escape
138from webob.acceptparse import create_accept_header
140from pyramid.compat import class_types, text_type, binary_type, text_
142from pyramid.interfaces import IExceptionResponse
143from pyramid.response import Response
146def _no_escape(value):
147 if value is None:
148 return ''
149 if not isinstance(value, text_type):
150 if hasattr(value, '__unicode__'):
151 value = value.__unicode__()
152 if isinstance(value, binary_type):
153 value = text_(value, 'utf-8')
154 else:
155 value = text_type(value)
156 return value
159@implementer(IExceptionResponse)
160class HTTPException(Response, Exception):
161 # You should set in subclasses:
162 # code = 200
163 # title = 'OK'
164 # explanation = 'why this happens'
165 # body_template_obj = Template('response template')
166 #
167 # This class itself uses the error code "520" with the error message/title
168 # of "Unknown Error". This is not an RFC standard, however it is
169 # implemented in practice. Sub-classes should be overriding the default
170 # values and 520 should not be seen in the wild from Pyramid applications.
171 # Due to changes in WebOb, a code of "None" is not valid, and WebOb due to
172 # more strict error checking rejects it now.
174 # differences from webob.exc.WSGIHTTPException:
175 #
176 # - doesn't use "strip_tags" (${br} placeholder for <br/>, no other html
177 # in default body template)
178 #
179 # - __call__ never generates a new Response, it always mutates self
180 #
181 # - explicitly sets self.message = detail to prevent whining by Python
182 # 2.6.5+ access of Exception.message
183 #
184 # - its base class of HTTPException is no longer a Python 2.4 compatibility
185 # shim; it's purely a base class that inherits from Exception. This
186 # implies that this class' ``exception`` property always returns
187 # ``self`` (it exists only for bw compat at this point).
188 #
189 # - documentation improvements (Pyramid-specific docstrings where
190 # necessary)
191 #
192 code = 520
193 title = 'Unknown Error'
194 explanation = ''
195 body_template_obj = Template(
196 '''\
197${explanation}${br}${br}
198${detail}
199${html_comment}
200'''
201 )
203 plain_template_obj = Template(
204 '''\
205${status}
207${body}'''
208 )
210 html_template_obj = Template(
211 '''\
212<html>
213 <head>
214 <title>${status}</title>
215 </head>
216 <body>
217 <h1>${status}</h1>
218 ${body}
219 </body>
220</html>'''
221 )
223 # Set this to True for responses that should have no request body
224 empty_body = False
226 def __init__(
227 self,
228 detail=None,
229 headers=None,
230 comment=None,
231 body_template=None,
232 json_formatter=None,
233 **kw
234 ):
235 status = '%s %s' % (self.code, self.title)
236 Response.__init__(self, status=status, **kw)
237 Exception.__init__(self, detail)
238 self.detail = self.message = detail
239 if headers:
240 self.headers.extend(headers)
241 self.comment = comment
242 if body_template is not None:
243 self.body_template = body_template
244 self.body_template_obj = Template(body_template)
245 if json_formatter is not None:
246 self._json_formatter = json_formatter
248 if self.empty_body:
249 del self.content_type
250 del self.content_length
252 def __str__(self):
253 return str(self.detail) if self.detail else self.explanation
255 def _json_formatter(self, status, body, title, environ):
256 return {'message': body, 'code': status, 'title': self.title}
258 def prepare(self, environ):
259 if not self.has_body and not self.empty_body:
260 html_comment = ''
261 comment = self.comment or ''
262 accept_value = environ.get('HTTP_ACCEPT', '')
263 accept = create_accept_header(accept_value)
264 # Attempt to match text/html or application/json, if those don't
265 # match, we will fall through to defaulting to text/plain
266 acceptable = accept.acceptable_offers(
267 ['text/html', 'application/json']
268 )
269 acceptable = [offer[0] for offer in acceptable] + ['text/plain']
270 match = acceptable[0]
272 if match == 'text/html':
273 self.content_type = 'text/html'
274 escape = _html_escape
275 page_template = self.html_template_obj
276 br = '<br/>'
277 if comment:
278 html_comment = '<!-- %s -->' % escape(comment)
279 elif match == 'application/json':
280 self.content_type = 'application/json'
281 self.charset = None
282 escape = _no_escape
283 br = '\n'
284 if comment:
285 html_comment = escape(comment)
287 class JsonPageTemplate(object):
288 def __init__(self, excobj):
289 self.excobj = excobj
291 def substitute(self, status, body):
292 jsonbody = self.excobj._json_formatter(
293 status=status,
294 body=body,
295 title=self.excobj.title,
296 environ=environ,
297 )
298 return json.dumps(jsonbody)
300 page_template = JsonPageTemplate(self)
301 else:
302 self.content_type = 'text/plain'
303 escape = _no_escape
304 page_template = self.plain_template_obj
305 br = '\n'
306 if comment:
307 html_comment = escape(comment)
308 args = {
309 'br': br,
310 'explanation': escape(self.explanation),
311 'detail': escape(self.detail or ''),
312 'comment': escape(comment),
313 'html_comment': html_comment,
314 }
315 body_tmpl = self.body_template_obj
316 if HTTPException.body_template_obj is not body_tmpl:
317 # Custom template; add headers to args
318 for k, v in environ.items():
319 if (not k.startswith('wsgi.')) and ('.' in k):
320 # omit custom environ variables, stringifying them may
321 # trigger code that should not be executed here; see
322 # https://github.com/Pylons/pyramid/issues/239
323 continue
324 args[k] = escape(v)
325 for k, v in self.headers.items():
326 args[k.lower()] = escape(v)
327 body = body_tmpl.substitute(args)
328 page = page_template.substitute(status=self.status, body=body)
329 if isinstance(page, text_type):
330 page = page.encode(self.charset if self.charset else 'UTF-8')
331 self.app_iter = [page]
332 self.body = page
334 @property
335 def wsgi_response(self):
336 # bw compat only
337 return self
339 exception = wsgi_response # bw compat only
341 def __call__(self, environ, start_response):
342 # differences from webob.exc.WSGIHTTPException
343 #
344 # - does not try to deal with HEAD requests
345 #
346 # - does not manufacture a new response object when generating
347 # the default response
348 #
349 self.prepare(environ)
350 return Response.__call__(self, environ, start_response)
353WSGIHTTPException = HTTPException # b/c post 1.5
356class HTTPError(HTTPException):
357 """
358 base class for exceptions with status codes in the 400s and 500s
360 This is an exception which indicates that an error has occurred,
361 and that any work in progress should not be committed.
362 """
365class HTTPRedirection(HTTPException):
366 """
367 base class for exceptions with status codes in the 300s (redirections)
369 This is an abstract base class for 3xx redirection. It indicates
370 that further action needs to be taken by the user agent in order
371 to fulfill the request. It does not necessarly signal an error
372 condition.
373 """
376class HTTPSuccessful(HTTPException):
377 """
378 Base class for exceptions with status codes in the 200s (successful
379 responses)
380 """
383############################################################
384# 2xx success
385############################################################
388class HTTPOk(HTTPSuccessful):
389 """
390 subclass of :class:`~HTTPSuccessful`
392 Indicates that the request has succeeded.
394 code: 200, title: OK
395 """
397 code = 200
398 title = 'OK'
401class HTTPCreated(HTTPSuccessful):
402 """
403 subclass of :class:`~HTTPSuccessful`
405 This indicates that request has been fulfilled and resulted in a new
406 resource being created.
408 code: 201, title: Created
409 """
411 code = 201
412 title = 'Created'
415class HTTPAccepted(HTTPSuccessful):
416 """
417 subclass of :class:`~HTTPSuccessful`
419 This indicates that the request has been accepted for processing, but the
420 processing has not been completed.
422 code: 202, title: Accepted
423 """
425 code = 202
426 title = 'Accepted'
427 explanation = 'The request is accepted for processing.'
430class HTTPNonAuthoritativeInformation(HTTPSuccessful):
431 """
432 subclass of :class:`~HTTPSuccessful`
434 This indicates that the returned metainformation in the entity-header is
435 not the definitive set as available from the origin server, but is
436 gathered from a local or a third-party copy.
438 code: 203, title: Non-Authoritative Information
439 """
441 code = 203
442 title = 'Non-Authoritative Information'
445class HTTPNoContent(HTTPSuccessful):
446 """
447 subclass of :class:`~HTTPSuccessful`
449 This indicates that the server has fulfilled the request but does
450 not need to return an entity-body, and might want to return updated
451 metainformation.
453 code: 204, title: No Content
454 """
456 code = 204
457 title = 'No Content'
458 empty_body = True
461class HTTPResetContent(HTTPSuccessful):
462 """
463 subclass of :class:`~HTTPSuccessful`
465 This indicates that the server has fulfilled the request and
466 the user agent SHOULD reset the document view which caused the
467 request to be sent.
469 code: 205, title: Reset Content
470 """
472 code = 205
473 title = 'Reset Content'
474 empty_body = True
477class HTTPPartialContent(HTTPSuccessful):
478 """
479 subclass of :class:`~HTTPSuccessful`
481 This indicates that the server has fulfilled the partial GET
482 request for the resource.
484 code: 206, title: Partial Content
485 """
487 code = 206
488 title = 'Partial Content'
491# FIXME: add 207 Multi-Status (but it's complicated)
493############################################################
494# 3xx redirection
495############################################################
498class _HTTPMove(HTTPRedirection):
499 """
500 redirections which require a Location field
502 Since a 'Location' header is a required attribute of 301, 302, 303,
503 305 and 307 (but not 304), this base class provides the mechanics to
504 make this easy.
506 You must provide a ``location`` keyword argument.
507 """
509 # differences from webob.exc._HTTPMove:
510 #
511 # - ${location} isn't wrapped in an <a> tag in body
512 #
513 # - location keyword arg defaults to ''
514 #
515 # - location isn't prepended with req.path_url when adding it as
516 # a header
517 #
518 # - ``location`` is first keyword (and positional) argument
519 #
520 # - ``add_slash`` argument is no longer accepted: code that passes
521 # add_slash argument to the constructor will receive an exception.
522 explanation = 'The resource has been moved to'
523 body_template_obj = Template(
524 '''\
525${explanation} ${location}; you should be redirected automatically.
526${detail}
527${html_comment}'''
528 )
530 def __init__(
531 self,
532 location='',
533 detail=None,
534 headers=None,
535 comment=None,
536 body_template=None,
537 **kw
538 ):
539 if location is None:
540 raise ValueError("HTTP redirects need a location to redirect to.")
541 super(_HTTPMove, self).__init__(
542 detail=detail,
543 headers=headers,
544 comment=comment,
545 body_template=body_template,
546 location=location,
547 **kw
548 )
551class HTTPMultipleChoices(_HTTPMove):
552 """
553 subclass of :class:`~_HTTPMove`
555 This indicates that the requested resource corresponds to any one
556 of a set of representations, each with its own specific location,
557 and agent-driven negotiation information is being provided so that
558 the user can select a preferred representation and redirect its
559 request to that location.
561 code: 300, title: Multiple Choices
562 """
564 code = 300
565 title = 'Multiple Choices'
568class HTTPMovedPermanently(_HTTPMove):
569 """
570 subclass of :class:`~_HTTPMove`
572 This indicates that the requested resource has been assigned a new
573 permanent URI and any future references to this resource SHOULD use
574 one of the returned URIs.
576 code: 301, title: Moved Permanently
577 """
579 code = 301
580 title = 'Moved Permanently'
583class HTTPFound(_HTTPMove):
584 """
585 subclass of :class:`~_HTTPMove`
587 This indicates that the requested resource resides temporarily under
588 a different URI.
590 code: 302, title: Found
591 """
593 code = 302
594 title = 'Found'
595 explanation = 'The resource was found at'
598# This one is safe after a POST (the redirected location will be
599# retrieved with GET):
600class HTTPSeeOther(_HTTPMove):
601 """
602 subclass of :class:`~_HTTPMove`
604 This indicates that the response to the request can be found under
605 a different URI and SHOULD be retrieved using a GET method on that
606 resource.
608 code: 303, title: See Other
609 """
611 code = 303
612 title = 'See Other'
615class HTTPNotModified(HTTPRedirection):
616 """
617 subclass of :class:`~HTTPRedirection`
619 This indicates that if the client has performed a conditional GET
620 request and access is allowed, but the document has not been
621 modified, the server SHOULD respond with this status code.
623 code: 304, title: Not Modified
624 """
626 # FIXME: this should include a date or etag header
627 code = 304
628 title = 'Not Modified'
629 empty_body = True
632class HTTPUseProxy(_HTTPMove):
633 """
634 subclass of :class:`~_HTTPMove`
636 This indicates that the requested resource MUST be accessed through
637 the proxy given by the Location field.
639 code: 305, title: Use Proxy
640 """
642 # Not a move, but looks a little like one
643 code = 305
644 title = 'Use Proxy'
645 explanation = 'The resource must be accessed through a proxy located at'
648class HTTPTemporaryRedirect(_HTTPMove):
649 """
650 subclass of :class:`~_HTTPMove`
652 This indicates that the requested resource resides temporarily
653 under a different URI.
655 code: 307, title: Temporary Redirect
656 """
658 code = 307
659 title = 'Temporary Redirect'
662class HTTPPermanentRedirect(_HTTPMove):
663 """
664 subclass of :class:`~_HTTPMove`
666 This indicates that the requested resource resides permanently
667 under a different URI and that the request method must not be
668 changed.
670 code: 308, title: Permanent Redirect
671 """
673 code = 308
674 title = 'Permanent Redirect'
677############################################################
678# 4xx client error
679############################################################
682class HTTPClientError(HTTPError):
683 """
684 base class for the 400s, where the client is in error
686 This is an error condition in which the client is presumed to be
687 in-error. This is an expected problem, and thus is not considered
688 a bug. A server-side traceback is not warranted. Unless specialized,
689 this is a '400 Bad Request'
690 """
692 code = 400
693 title = 'Bad Request'
696class HTTPBadRequest(HTTPClientError):
697 """
698 subclass of :class:`~HTTPClientError`
700 This indicates that the body or headers failed validity checks,
701 preventing the server from being able to continue processing.
703 code: 400, title: Bad Request
704 """
706 explanation = (
707 'The server could not comply with the request since '
708 'it is either malformed or otherwise incorrect.'
709 )
712class HTTPUnauthorized(HTTPClientError):
713 """
714 subclass of :class:`~HTTPClientError`
716 This indicates that the request requires user authentication.
718 code: 401, title: Unauthorized
719 """
721 code = 401
722 title = 'Unauthorized'
723 explanation = (
724 'This server could not verify that you are authorized to '
725 'access the document you requested. Either you supplied the '
726 'wrong credentials (e.g., bad password), or your browser '
727 'does not understand how to supply the credentials required.'
728 )
731class HTTPPaymentRequired(HTTPClientError):
732 """
733 subclass of :class:`~HTTPClientError`
735 code: 402, title: Payment Required
736 """
738 code = 402
739 title = 'Payment Required'
740 explanation = 'Access was denied for financial reasons.'
743class HTTPForbidden(HTTPClientError):
744 """
745 subclass of :class:`~HTTPClientError`
747 This indicates that the server understood the request, but is
748 refusing to fulfill it.
750 code: 403, title: Forbidden
752 Raise this exception within :term:`view` code to immediately return the
753 :term:`forbidden view` to the invoking user. Usually this is a basic
754 ``403`` page, but the forbidden view can be customized as necessary. See
755 :ref:`changing_the_forbidden_view`. A ``Forbidden`` exception will be
756 the ``context`` of a :term:`Forbidden View`.
758 This exception's constructor treats two arguments specially. The first
759 argument, ``detail``, should be a string. The value of this string will
760 be used as the ``message`` attribute of the exception object. The second
761 special keyword argument, ``result`` is usually an instance of
762 :class:`pyramid.security.Denied` or :class:`pyramid.security.ACLDenied`
763 each of which indicates a reason for the forbidden error. However,
764 ``result`` is also permitted to be just a plain boolean ``False`` object
765 or ``None``. The ``result`` value will be used as the ``result``
766 attribute of the exception object. It defaults to ``None``.
768 The :term:`Forbidden View` can use the attributes of a Forbidden
769 exception as necessary to provide extended information in an error
770 report shown to a user.
771 """
773 # differences from webob.exc.HTTPForbidden:
774 #
775 # - accepts a ``result`` keyword argument
776 #
777 # - overrides constructor to set ``self.result``
778 #
779 # differences from older ``pyramid.exceptions.Forbidden``:
780 #
781 # - ``result`` must be passed as a keyword argument.
782 #
783 code = 403
784 title = 'Forbidden'
785 explanation = 'Access was denied to this resource.'
787 def __init__(
788 self,
789 detail=None,
790 headers=None,
791 comment=None,
792 body_template=None,
793 result=None,
794 **kw
795 ):
796 HTTPClientError.__init__(
797 self,
798 detail=detail,
799 headers=headers,
800 comment=comment,
801 body_template=body_template,
802 **kw
803 )
804 self.result = result
807class HTTPNotFound(HTTPClientError):
808 """
809 subclass of :class:`~HTTPClientError`
811 This indicates that the server did not find anything matching the
812 Request-URI.
814 code: 404, title: Not Found
816 Raise this exception within :term:`view` code to immediately
817 return the :term:`Not Found View` to the invoking user. Usually
818 this is a basic ``404`` page, but the Not Found View can be
819 customized as necessary. See :ref:`changing_the_notfound_view`.
821 This exception's constructor accepts a ``detail`` argument
822 (the first argument), which should be a string. The value of this
823 string will be available as the ``message`` attribute of this exception,
824 for availability to the :term:`Not Found View`.
825 """
827 code = 404
828 title = 'Not Found'
829 explanation = 'The resource could not be found.'
832class HTTPMethodNotAllowed(HTTPClientError):
833 """
834 subclass of :class:`~HTTPClientError`
836 This indicates that the method specified in the Request-Line is
837 not allowed for the resource identified by the Request-URI.
839 code: 405, title: Method Not Allowed
840 """
842 # differences from webob.exc.HTTPMethodNotAllowed:
843 #
844 # - body_template_obj uses ${br} instead of <br />
845 code = 405
846 title = 'Method Not Allowed'
847 body_template_obj = Template(
848 '''\
849The method ${REQUEST_METHOD} is not allowed for this resource. ${br}${br}
850${detail}'''
851 )
854class HTTPNotAcceptable(HTTPClientError):
855 """
856 subclass of :class:`~HTTPClientError`
858 This indicates the resource identified by the request is only
859 capable of generating response entities which have content
860 characteristics not acceptable according to the accept headers
861 sent in the request.
863 code: 406, title: Not Acceptable
864 """
866 # differences from webob.exc.HTTPNotAcceptable:
867 #
868 # - "template" attribute left off (useless, bug in webob?)
869 code = 406
870 title = 'Not Acceptable'
873class HTTPProxyAuthenticationRequired(HTTPClientError):
874 """
875 subclass of :class:`~HTTPClientError`
877 This is similar to 401, but indicates that the client must first
878 authenticate itself with the proxy.
880 code: 407, title: Proxy Authentication Required
881 """
883 code = 407
884 title = 'Proxy Authentication Required'
885 explanation = 'Authentication with a local proxy is needed.'
888class HTTPRequestTimeout(HTTPClientError):
889 """
890 subclass of :class:`~HTTPClientError`
892 This indicates that the client did not produce a request within
893 the time that the server was prepared to wait.
895 code: 408, title: Request Timeout
896 """
898 code = 408
899 title = 'Request Timeout'
900 explanation = (
901 'The server has waited too long for the request to '
902 'be sent by the client.'
903 )
906class HTTPConflict(HTTPClientError):
907 """
908 subclass of :class:`~HTTPClientError`
910 This indicates that the request could not be completed due to a
911 conflict with the current state of the resource.
913 code: 409, title: Conflict
914 """
916 code = 409
917 title = 'Conflict'
918 explanation = (
919 'There was a conflict when trying to complete ' 'your request.'
920 )
923class HTTPGone(HTTPClientError):
924 """
925 subclass of :class:`~HTTPClientError`
927 This indicates that the requested resource is no longer available
928 at the server and no forwarding address is known.
930 code: 410, title: Gone
931 """
933 code = 410
934 title = 'Gone'
935 explanation = (
936 'This resource is no longer available. No forwarding '
937 'address is given.'
938 )
941class HTTPLengthRequired(HTTPClientError):
942 """
943 subclass of :class:`~HTTPClientError`
945 This indicates that the server refuses to accept the request
946 without a defined Content-Length.
948 code: 411, title: Length Required
949 """
951 code = 411
952 title = 'Length Required'
953 explanation = 'Content-Length header required.'
956class HTTPPreconditionFailed(HTTPClientError):
957 """
958 subclass of :class:`~HTTPClientError`
960 This indicates that the precondition given in one or more of the
961 request-header fields evaluated to false when it was tested on the
962 server.
964 code: 412, title: Precondition Failed
965 """
967 code = 412
968 title = 'Precondition Failed'
969 explanation = 'Request precondition failed.'
972class HTTPRequestEntityTooLarge(HTTPClientError):
973 """
974 subclass of :class:`~HTTPClientError`
976 This indicates that the server is refusing to process a request
977 because the request entity is larger than the server is willing or
978 able to process.
980 code: 413, title: Request Entity Too Large
981 """
983 code = 413
984 title = 'Request Entity Too Large'
985 explanation = 'The body of your request was too large for this server.'
988class HTTPRequestURITooLong(HTTPClientError):
989 """
990 subclass of :class:`~HTTPClientError`
992 This indicates that the server is refusing to service the request
993 because the Request-URI is longer than the server is willing to
994 interpret.
996 code: 414, title: Request-URI Too Long
997 """
999 code = 414
1000 title = 'Request-URI Too Long'
1001 explanation = 'The request URI was too long for this server.'
1004class HTTPUnsupportedMediaType(HTTPClientError):
1005 """
1006 subclass of :class:`~HTTPClientError`
1008 This indicates that the server is refusing to service the request
1009 because the entity of the request is in a format not supported by
1010 the requested resource for the requested method.
1012 code: 415, title: Unsupported Media Type
1013 """
1015 # differences from webob.exc.HTTPUnsupportedMediaType:
1016 #
1017 # - "template_obj" attribute left off (useless, bug in webob?)
1018 code = 415
1019 title = 'Unsupported Media Type'
1022class HTTPRequestRangeNotSatisfiable(HTTPClientError):
1023 """
1024 subclass of :class:`~HTTPClientError`
1026 The server SHOULD return a response with this status code if a
1027 request included a Range request-header field, and none of the
1028 range-specifier values in this field overlap the current extent
1029 of the selected resource, and the request did not include an
1030 If-Range request-header field.
1032 code: 416, title: Request Range Not Satisfiable
1033 """
1035 code = 416
1036 title = 'Request Range Not Satisfiable'
1037 explanation = 'The Range requested is not available.'
1040class HTTPExpectationFailed(HTTPClientError):
1041 """
1042 subclass of :class:`~HTTPClientError`
1044 This indidcates that the expectation given in an Expect
1045 request-header field could not be met by this server.
1047 code: 417, title: Expectation Failed
1048 """
1050 code = 417
1051 title = 'Expectation Failed'
1052 explanation = 'Expectation failed.'
1055class HTTPUnprocessableEntity(HTTPClientError):
1056 """
1057 subclass of :class:`~HTTPClientError`
1059 This indicates that the server is unable to process the contained
1060 instructions.
1062 May be used to notify the client that their JSON/XML is well formed, but
1063 not correct for the current request.
1065 See RFC4918 section 11 for more information.
1067 code: 422, title: Unprocessable Entity
1068 """
1070 # Note: from WebDAV
1071 code = 422
1072 title = 'Unprocessable Entity'
1073 explanation = 'Unable to process the contained instructions'
1076class HTTPLocked(HTTPClientError):
1077 """
1078 subclass of :class:`~HTTPClientError`
1080 This indicates that the resource is locked.
1082 code: 423, title: Locked
1083 """
1085 # Note: from WebDAV
1086 code = 423
1087 title = 'Locked'
1088 explanation = 'The resource is locked'
1091class HTTPFailedDependency(HTTPClientError):
1092 """
1093 subclass of :class:`~HTTPClientError`
1095 This indicates that the method could not be performed because the
1096 requested action depended on another action and that action failed.
1098 code: 424, title: Failed Dependency
1099 """
1101 # Note: from WebDAV
1102 code = 424
1103 title = 'Failed Dependency'
1104 explanation = (
1105 'The method could not be performed because the requested '
1106 'action dependended on another action and that action failed'
1107 )
1110class HTTPPreconditionRequired(HTTPClientError):
1111 """
1112 subclass of :class:`~HTTPClientError`
1114 This indicates that the origin server requires the
1115 request to be conditional.
1117 Its typical use is to avoid the "lost update" problem, where a client
1118 GETs a resource's state, modifies it, and PUTs it back to the server,
1119 when meanwhile a third party has modified the state on the server,
1120 leading to a conflict. By requiring requests to be conditional, the
1121 server can assure that clients are working with the correct copies.
1123 RFC 6585.3
1125 code: 428, title: Precondition Required
1126 """
1128 code = 428
1129 title = 'Precondition Required'
1130 explanation = 'The origin server requires the request to be conditional.'
1133class HTTPTooManyRequests(HTTPClientError):
1134 """
1135 subclass of :class:`~HTTPClientError`
1137 This indicates that the user has sent too many
1138 requests in a given amount of time ("rate limiting").
1140 RFC 6585.4
1142 code: 429, title: Too Many Requests
1143 """
1145 code = 429
1146 title = 'Too Many Requests'
1147 explanation = (
1148 'The action could not be performed because there were too '
1149 'many requests by the client.'
1150 )
1153class HTTPRequestHeaderFieldsTooLarge(HTTPClientError):
1154 """
1155 subclass of :class:`~HTTPClientError`
1157 This indicates that the server is unwilling to process
1158 the request because its header fields are too large. The request MAY
1159 be resubmitted after reducing the size of the request header fields.
1161 RFC 6585.5
1163 code: 431, title: Request Header Fields Too Large
1164 """
1166 code = 431
1167 title = 'Request Header Fields Too Large'
1168 explanation = 'The requests header fields were too large.'
1171############################################################
1172# 5xx Server Error
1173############################################################
1174# Response status codes beginning with the digit "5" indicate cases in
1175# which the server is aware that it has erred or is incapable of
1176# performing the request. Except when responding to a HEAD request, the
1177# server SHOULD include an entity containing an explanation of the error
1178# situation, and whether it is a temporary or permanent condition. User
1179# agents SHOULD display any included entity to the user. These response
1180# codes are applicable to any request method.
1183class HTTPServerError(HTTPError):
1184 """
1185 base class for the 500s, where the server is in-error
1187 This is an error condition in which the server is presumed to be
1188 in-error. Unless specialized, this is a '500 Internal Server Error'.
1189 """
1191 code = 500
1192 title = 'Internal Server Error'
1195class HTTPInternalServerError(HTTPServerError):
1196 """
1197 subclass of :class:`~HTTPServerError`
1199 This indicates that the server encountered an unexpected condition
1200 which prevented it from fulfilling the request.
1202 code: 500, title: Internal Server Error
1203 """
1205 explanation = (
1206 'The server has either erred or is incapable of performing '
1207 'the requested operation.'
1208 )
1211class HTTPNotImplemented(HTTPServerError):
1212 """
1213 subclass of :class:`~HTTPServerError`
1215 This indicates that the server does not support the functionality
1216 required to fulfill the request.
1218 code: 501, title: Not Implemented
1219 """
1221 # differences from webob.exc.HTTPNotAcceptable:
1222 #
1223 # - "template" attr left off (useless, bug in webob?)
1224 code = 501
1225 title = 'Not Implemented'
1228class HTTPBadGateway(HTTPServerError):
1229 """
1230 subclass of :class:`~HTTPServerError`
1232 This indicates that the server, while acting as a gateway or proxy,
1233 received an invalid response from the upstream server it accessed
1234 in attempting to fulfill the request.
1236 code: 502, title: Bad Gateway
1237 """
1239 code = 502
1240 title = 'Bad Gateway'
1241 explanation = 'Bad gateway.'
1244class HTTPServiceUnavailable(HTTPServerError):
1245 """
1246 subclass of :class:`~HTTPServerError`
1248 This indicates that the server is currently unable to handle the
1249 request due to a temporary overloading or maintenance of the server.
1251 code: 503, title: Service Unavailable
1252 """
1254 code = 503
1255 title = 'Service Unavailable'
1256 explanation = (
1257 'The server is currently unavailable. '
1258 'Please try again at a later time.'
1259 )
1262class HTTPGatewayTimeout(HTTPServerError):
1263 """
1264 subclass of :class:`~HTTPServerError`
1266 This indicates that the server, while acting as a gateway or proxy,
1267 did not receive a timely response from the upstream server specified
1268 by the URI (e.g. HTTP, FTP, LDAP) or some other auxiliary server
1269 (e.g. DNS) it needed to access in attempting to complete the request.
1271 code: 504, title: Gateway Timeout
1272 """
1274 code = 504
1275 title = 'Gateway Timeout'
1276 explanation = 'The gateway has timed out.'
1279class HTTPVersionNotSupported(HTTPServerError):
1280 """
1281 subclass of :class:`~HTTPServerError`
1283 This indicates that the server does not support, or refuses to
1284 support, the HTTP protocol version that was used in the request
1285 message.
1287 code: 505, title: HTTP Version Not Supported
1288 """
1290 code = 505
1291 title = 'HTTP Version Not Supported'
1292 explanation = 'The HTTP version is not supported.'
1295class HTTPInsufficientStorage(HTTPServerError):
1296 """
1297 subclass of :class:`~HTTPServerError`
1299 This indicates that the server does not have enough space to save
1300 the resource.
1302 code: 507, title: Insufficient Storage
1303 """
1305 code = 507
1306 title = 'Insufficient Storage'
1307 explanation = 'There was not enough space to save the resource'
1310def exception_response(status_code, **kw):
1311 """Creates an HTTP exception based on a status code. Example::
1313 raise exception_response(404) # raises an HTTPNotFound exception.
1315 The values passed as ``kw`` are provided to the exception's constructor.
1316 """
1317 exc = status_map[status_code](**kw)
1318 return exc
1321def default_exceptionresponse_view(context, request):
1322 if not isinstance(context, Exception):
1323 # backwards compat for an exception response view registered via
1324 # config.set_notfound_view or config.set_forbidden_view
1325 # instead of as a proper exception view
1326 context = request.exception or context
1327 return context # assumed to be an IResponse
1330status_map = {}
1331code = None
1332for name, value in list(globals().items()):
1333 if (
1334 isinstance(value, class_types)
1335 and issubclass(value, HTTPException)
1336 and value not in {HTTPClientError, HTTPServerError}
1337 and not name.startswith('_')
1338 ):
1339 code = getattr(value, 'code', None)
1340 if code:
1341 status_map[code] = value
1342del name, value, code