"""HTTP status reporting.
This module provides classes corresponding to the various HTTP redirection
and error codes. A typical page handler can report an HTTP status (other than
the regular "200 OK") by raising an instance of one of these classes.
"""
from wsgiref.util import request_uri
from urllib.parse import urljoin
from ll.xist.ns import html
[docs]class HTTPStatus (Exception):
"""Top-level class for HTTP status reporting.
"""
def __init__ (self, status, description, body=None):
super (HTTPStatus, self).__init__ ()
self.__status = status
self.__description = description
self.__body = body
@property
def status (self):
return self.__status
@property
def description (self):
return self.__description
[docs] def get_status (self):
return '%i %s' % (self.status, self.description)
[docs] def get_body (self):
return self.__body or html.p ("HTTP Error")
[docs]class HTTPRedirection (HTTPStatus):
"""HTTP redirection status codes (3xx).
"""
def __init__ (self, status, description, url):
super (HTTPRedirection, self).__init__ (status, description)
# If string supplied as Unicode, need to reduce to str as regular
# str must be supplied to flup start_response function.
# URLs are ASCII-only anyway; non-ASCII characters must be reprsented
# using %-sequences so this does not actually restrict anything.
self.__url = str (url)
@property
def url (self):
return self.__url
[docs]class HTTPMovedPermanently (HTTPRedirection):
def __init__ (self, url):
super (HTTPMovedPermanently, self).__init__ (301, "Moved Permanently", url)
[docs]class HTTPFound (HTTPRedirection):
def __init__ (self, url):
super (HTTPFound, self).__init__ (302, "Found", url)
[docs]class HTTPSeeOther (HTTPRedirection):
def __init__ (self, url):
super (HTTPSeeOther, self).__init__ (303, "See Other", url)
[docs]class HTTPTemporaryRedirect (HTTPRedirection):
def __init__ (self, url):
super (HTTPTemporaryRedirect, self).__init__ (307, "Temporary Redirect", url)
[docs]class HTTPError (HTTPStatus):
"""HTTP error status codes (4xx, 5xx).
"""
pass
[docs]class HTTPClientError (HTTPError):
"""HTTP client error status codes (4xx).
"""
pass
[docs]class HTTPBadRequest (HTTPClientError):
def __init__ (self):
super (HTTPBadRequest, self).__init__ (400, "Bad Request")
[docs] @staticmethod
def handler (environ, start_response):
raise HTTPBadRequest ()
[docs]class HTTPForbidden (HTTPClientError):
def __init__ (self):
super (HTTPForbidden, self).__init__ (403, "Forbidden")
[docs] @staticmethod
def handler (environ, start_response):
raise HTTPForbidden ()
[docs]class HTTPNotFound (HTTPClientError):
def __init__ (self):
super (HTTPNotFound, self).__init__ (404, "Not Found")
[docs] @staticmethod
def handler (environ, start_response):
raise HTTPNotFound ()
[docs]class HTTPMethodNotAllowed (HTTPClientError):
def __init__ (self, methods):
super (HTTPMethodNotAllowed, self).__init__ (405, "Method Not Allowed", body=html.ul (html.li (method) for method in methods))
self.__methods = tuple (methods)
@property
def methods (self):
return self.__methods
[docs] @staticmethod
def handler (methods):
def result (environ, start_response):
raise HTTPMethodNotAllowed (methods)
return result
[docs]class HTTPGone (HTTPClientError):
def __init__ (self):
super (HTTPGone, self).__init__ (410, "Gone")
[docs] @staticmethod
def handler (environ, start_response):
raise HTTPGone ()
[docs]class HTTPServerError (HTTPError):
"""HTTP server error status codes (5xx).
"""
pass
[docs]class HTTPInternalServerError (HTTPServerError):
def __init__ (self, body=None):
super (HTTPInternalServerError, self).__init__ (500, "Internal Server Error", body)