WhakerPy 1.0

https://sourceforge.net/projects/whakerpy/

Module whakerpy.httpd

Class HTTPDHandler

Description

Web-based application HTTPD handler.

This class is used to handle the HTTP requests that arrive at the server.

This class is instantiated by the server each time a request is received and then a response is created. This is an HTTPD handler for any Web-based application server. It parses the request and the headers, then call a specific method depending on the request type.

In this handler, HTML pages are supposed to not be static. Instead, they are serialized from an HTMLTree instance -- so not read from disk. The server contains the page's bakery, the handler is then asking the server page's bakery to get the html content and response status.

The parent server is supposed to have all the pages as members in a dictionary, i.e. it's a sppasBaseHTTPDServer. Each page has a bakery to create the response content. However, this handler can also be used with any other http.server.ThreadingHTTPServer.

The currently supported HTTPD responses status are:

  • 200: OK
  • 205: Reset Content
  • 403: Forbidden
  • 404: Not Found
  • 410: Gone
  • 418: I'm not a teapot

Constructor

View Source
def __init__(self, request, client_address, server):
    self.request = request
    self.client_address = client_address
    self.server = server
    self.setup()
    try:
        self.handle()
    finally:
        self.finish()

Public functions

do_HEAD

Prepare the response to a HEAD request.

View Source
def do_HEAD(self) -> None:
    """Prepare the response to a HEAD request."""
    logging.debug('HEAD -- requested: {}'.format(self.path))
    self._set_headers(200)

do_GET

Prepare the response to a GET request.

View Source
def do_GET(self) -> None:
    """Prepare the response to a GET request."""
    logging.debug(' ---- DO GET -- requested: {}'.format(self.path))
    handler_utils = HTTPDHandlerUtils(self.headers, self.path, self.__get_default_page())
    self.path = handler_utils.get_path()
    mime_type = HTTPDHandlerUtils.get_mime_type(self.path)
    if os.path.exists(handler_utils.get_path()) or os.path.exists(handler_utils.get_path()[1:]):
        content, status = handler_utils.static_content(self.path[1:])
    elif mime_type == 'text/html':
        content, status = self._bakery(handler_utils, dict(), mime_type)
    else:
        content, status = handler_utils.static_content(self.path[1:])
    self._response(content, status.code, mime_type)

do_POST

Prepare the response to a POST request.

View Source
def do_POST(self) -> None:
    """Prepare the response to a POST request."""
    logging.debug(' ----- DO POST -- requested: {}'.format(self.path))
    handler_utils = HTTPDHandlerUtils(self.headers, self.path, self.__get_default_page())
    self.path = handler_utils.get_path()
    events, accept = handler_utils.process_post(self.rfile)
    content, status = self._bakery(handler_utils, events, accept)
    self._response(content, status.code, accept)

log_request

Override. For a quiet handler pls!!!.

Parameters
  • code
  • size
View Source
def log_request(self, code='-', size='-') -> None:
    """Override. For a quiet handler pls!!!."""
    pass

Private functions

_set_headers

Set the HTTPD response headers.

Parameters
  • status: (int) A response status.
  • mime_type: (str) The mime type of the file response
Raises

sppasHTTPDValueError

View Source
def _set_headers(self, status: int, mime_type: str=None) -> None:
    """Set the HTTPD response headers.

        :param status: (int) A response status.
        :param mime_type: (str) The mime type of the file response

        :raises: sppasHTTPDValueError

        """
    status = HTTPDStatus.check(status)
    self.send_response(status)
    if mime_type is not None:
        self.send_header('Content-Type', mime_type)
    self.end_headers()

_response

Make the appropriate HTTPD response.

Parameters
  • content: (bytes) The HTML response content
  • status: (int) The HTTPD status code of the response
  • mime_type: (str) The mime type of the file response
View Source
def _response(self, content: bytes, status: int, mime_type: str=None) -> None:
    """Make the appropriate HTTPD response.

        :param content: (bytes) The HTML response content
        :param status: (int) The HTTPD status code of the response
        :param mime_type: (str) The mime type of the file response

        """
    self._set_headers(status, mime_type)
    self.wfile.write(content)
    if status == 410:
        self.server.shutdown()

_bakery

Process the events and return the html page content or json data and status.

Parameters
  • handler_utils: (HTTPDhandlerUtils)
  • events: (dict) key=event name, value=event value
  • mime_type: (str) The mime type of the file response
Returns
  • tuple(bytes, HTTPDStatus) the content of the response the httpd status
View Source
def _bakery(self, handler_utils: HTTPDHandlerUtils, events: dict, mime_type: str) -> tuple:
    """Process the events and return the html page content or json data and status.

        :param handler_utils: (HTTPDhandlerUtils)
        :param events: (dict) key=event name, value=event value
        :param mime_type: (str) The mime type of the file response

        :return: tuple(bytes, HTTPDStatus) the content of the response the httpd status

        """
    if hasattr(self.server, 'page_bakery') is False:
        return handler_utils.static_content(self.path[1:])
    content, status = self.server.page_bakery(handler_utils.get_page_name(), self.headers, events, handler_utils.has_to_return_data(mime_type))
    return (content, status)

Protected functions

__get_default_page

Get the default page in case if the url doesn't specify any page.

Returns
  • (str) the default page name
View Source
def __get_default_page(self) -> str:
    """Get the default page in case if the url doesn't specify any page.

        :return: (str) the default page name

        """
    try:
        default = self.server.default()
    except AttributeError:
        default = 'index.html'
    return default