# Module `lib.server.httprequest`

These classes manage http responses and requests. The set of request and response are in bytes format. I no longer use tools.strings., because they are between 20 and 30 times slower. It may sound a bit more complicated, but it's a lot quick.

Expand source code

    # Distributed under Pycameresp License
    # Copyright (c) 2023 Remi BERTHOLET
    # historically based on :
    # https://github.com/jczic/MicroWebSrv/blob/master/microWebSocket.py
    # but I have modified a lot, there must still be some original functions.
    # pylint:disable=consider-using-f-string
    """ These classes manage http responses and requests.
    The set of request and response are in bytes format.
    I no longer use tools.strings., because they are between 20 and 30 times slower.
    It may sound a bit more complicated, but it's a lot quick.
    """
    import hashlib
    import time
    from binascii import hexlify, b2a_base64
    import collections
    import server.stream
    import server.urlparser
    import tools.logger
    import tools.filesystem
    import tools.strings

    MIMES = {\
            b".txt"   : b"text/plain",
            b".py"    : b"text/plain",
            b".html"  : b"text/html",
            b".css"   : b"text/css",
            b".htm"   : b"text/html",
            b".csv"   : b"text/csv",
            b".log"   : b"text/plain",
            b".1"     : b"text/plain",
            b".2"     : b"text/plain",
            b".3"     : b"text/plain",
            b".4"     : b"text/plain",
            b".js"    : b"application/javascript",
            b".xml"   : b"application/xml",
            b".xhtml" : b"application/xhtml+xml",
            b".json"  : b"application/json",
            b".zip"   : b"application/zip",
            b".pdf"   : b"application/pdf",
            b".ts"    : b"application/typescript",
            b".woff"  : b"font/woff",
            b".woff2" : b"font/woff2",
            b".ttf"   : b"font/ttf",
            b".otf"   : b"font/otf",
            b".jpg"   : b"image/jpeg",
            b".png"   : b"image/png",
            b".gif"   : b"image/gif",
            b".jpeg"  : b"image/jpeg",
            b".svg"   : b"image/svg+xml",
            b".ico"   : b"image/x-icon",
            b".bin"   : b"application/octet-stream"
    }

    class Http:
            """ Http request or reponse """
            def __init__(self, request = True, remoteaddr= b"", port = 0, name=""):
                    """ Constructor from http request or response """
                    self.port       = port
                    self.name       = name
                    self.remoteaddr = remoteaddr
                    self.path       = b""
                    self.method     = b"POST"
                    self.headers    = collections.OrderedDict()
                    self.params     = collections.OrderedDict()
                    self.cookies    = collections.OrderedDict()
                    self.parts      = []
                    self.status     = 0
                    self.content    = None
                    self.content_file = None
                    self.identifier = None
                    self.request    = request
                    self.chunk_size = 0

            def __del__(self):
                    if self.content_file is not None:
                            tools.filesystem.remove(self.content_file)

            def get_expiration(self, expiration):
                    """ Get cookie expiration date """
                    result = b"; Max-Age=%d"%expiration
                    return result

            def get_cookie(self, name):
                    """ Get cookie value """
                    try:
                            return self.cookies.get(name, None)
                    except:
                            return None

            def set_cookie(self, name, value=None, expiration=None, http_only=False):
                    """ Set cookie """
                    if value is None:
                            if name in self.cookies:
                                    del self.cookies[name]
                    else:
                            self.cookies[name] = (value, expiration, http_only)

            def get_header(self, name):
                    """ Get the http request header """
                    try:
                            return self.headers.get(name, None)
                    except:
                            return None

            def set_header(self, name, value):
                    """ Set the http request header """
                    if value is None:
                            del self.headers[name]
                    else:
                            self.headers[name] = value

            def set_method(self, method):
                    """ Set http request method (POST or GET) """
                    self.method = method

            def get_path(self):
                    """ Get the path of the request or response """
                    return self.path

            def set_path(self, path):
                    """ Define the past of the request or response """
                    self.path = path

            def add_part(self, part):
                    """ Add part of the request. Used for multipart request """
                    self.parts.append(part)

            def get_status(self):
                    """ Get the status value """
                    return self.status

            def set_status(self, status):
                    """ Set the status value """
                    self.status = status

            def set_content(self, content):
                    """ Set the content of the request or response (can be an instance of html template) """
                    if type(content) == type(""):
                            self.content = ContentText(content)
                    else:
                            self.content = content

            def get_content(self):
                    """ Get the content of the request or response """
                    return self.content

            def get_id(self):
                    """ Get the unique identifier of the request or response. Used for multipart request """
                    hash_ = hashlib.sha256()
                    ids = b"%d"%time.time()
                    hash_.update(ids)
                    return hexlify(hash_.digest())[32:]

            async def unserialize(self, streamio):
                    """ Unserialize the request or response in the stream """
                    data = await streamio.readline()
                    if data != b"":
                            urlparser = server.urlparser.UrlParser(data, True)
                            spl = data.split()
                            if len(spl) >= 2:
                                    self.method = urlparser.method
                                    path = spl[1]
                                    if self.request is False:
                                            self.status = path
                                    self.path   = urlparser.path
                                    self.params = urlparser.params
                                    await self.unserialize_headers(streamio)
                            else:
                                    await self.read_content(streamio)

            async def read_content(self, streamio):
                    """ Read the content of http request """
                    if self.headers.get(b"Transfer-Encoding",b"") == b"chunked":
                            length = await streamio.readline()
                            length = eval(tools.strings.tostrings(b"0x%s"%length.strip()))
                            self.chunk_size = length
                            chunk = True
                    else:
                            length = int(self.headers.get(b"Content-Length",b"0"))
                            chunk = False
                    await self.read_data(length, streamio, chunk)

            async def read_data(self, length, streamio, chunk=False):
                    """ Read data with length """
                    # If data small write in memory
                    if length < 4096:
                            if chunk is False or self.content is None:
                                    self.content = b""
                            data = b""
                            while len(data) < length:
                                    data += await streamio.read(length - len(data))
                            self.content += data
                    # Data too big write in file
                    else:
                            self.content_file = "%d.tmp"%id(self)

                            print("Begin upload reception")
                            if chunk is False:
                                    attrib = "wb"
                            else:
                                    attrib = "ab"
                            with open(self.content_file, attrib) as content:
                                    while content.tell() < length:
                                            buffer = await streamio.read(length - content.tell())
                                            content.write(buffer)
                                            length_read = content.tell()
                                            print("  %d%% received"%(length_read*100 // length))
                            print("End upload reception")

            def get_content_filename(self):
                    """ Copy the content into file """
                    if self.content is not None:
                            self.content_file = "%d.tmp"%id(self)
                            with open(self.content_file, "wb") as content:
                                    content.write(self.content)
                            self.content = None
                    return self.content_file

            async def unserialize_headers(self, streamio):
                    """ Extract http header """
                    while True:
                            header = await streamio.readline()
                            if header == b"\r\n":
                                    if self.method == b"POST":
                                            await self.read_content(streamio)
                                            self.params = server.urlparser.UrlParser.parse_params(self.content)
                                    elif self.request is False or self.method == b"PUT":
                                            await self.read_content(streamio)
                                    break
                            name, value = header.split(b":", 1)
                            if name == b"Cookie":
                                    cookies = value.split(b";")
                                    for cookie in cookies:
                                            cookieName,cookieValue=cookie.split(b"=")
                                            self.cookies[cookieName.strip()] = cookieValue.strip()
                            else:
                                    self.headers[name] = value.strip()

            async def serialize(self, streamio, page=None):
                    """ Serialize request or response in the stream """
                    io = server.stream.Bufferedio(streamio)
                    result = await self.serialize_header(io)
                    result += await self.serialize_body(io)
                    if page:
                            await page.write(io)
                    await io.close()
                    return result

            async def serialize_header(self, streamio):
                    """ Serialize the header of http request or response """
                    if self.request:
                            result = await streamio.write(b"%s %s %s\r\n"%(self.method, self.path, b"HTTP/1.1"))
                    else:
                            result = await streamio.write(b"HTTP/1.1 %s NA\r\n"%(self.status))

                    try:
                            createIdentifier = False
                            if len(self.parts) > 0:
                                    createIdentifier = True
                            # If multipart request detected
                            if b"multipart" in self.headers[b"Content-Type"] :
                                    createIdentifier = True
                    except:
                            pass

                    # If identifier required (multipart request)
                    if self.identifier is None and createIdentifier:
                            self.identifier = self.get_id()

                    # Serialize http header
                    for header, value in self.headers.items():
                            if self.identifier is not None:
                                    if header == b"Content-Type":
                                            value += b"; boundary=%s"%self.identifier
                            result += await streamio.write(b"%s: %s\r\n"%(header, value))

                    # Serialize cookies
                    for name, value in self.cookies.items():
                            if self.request:
                                    setget = b""
                            else:
                                    setget = b"Set-"

                            http_only = b""
                            if len(value) >= 3:
                                    if value[2] is True:
                                            http_only = b"; HttpOnly"
                                    if name == b"session":
                                            http_only += b"; Path=/"
                            result += await streamio.write(b"%sCookie: %s=%s%s%s\r\n"%(setget, name, value[0], self.get_expiration(value[1]), http_only))
                    return result

            async def serialize_body(self, streamio):
                    """ Serialize body """
                    result = 0
                    no_end = False
                    # If content existing
                    if self.content is not None:
                            try:
                                    # If content is a bytes string
                                    if type(self.content) == type(b""):
                                            result += await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                                            result += await streamio.write(self.content)
                                    else:
                                            # Serialize object
                                            result += await self.content.serialize(streamio)
                                            no_end = True
                            except Exception as err:
                                    tools.logger.syslog(err)
                                    # Serialize error detected
                                    result += await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                                    result += await streamio.write(tools.strings.tostrings(tools.logger.exception(err)))
                    # If multipart detected
                    elif len(self.parts) > 0:
                            # If the header is a multipart
                            if self.headers[b"Content-Type"] == b"multipart/form-data":
                                    length = 0
                                    # Set the size of identifier
                                    for part in self.parts:
                                            length += 2
                                            length += await part.get_size(self.identifier)
                                    length += len(self.identifier)
                                    length += 6

                                    # Write multipart identifier
                                    result += await streamio.write(b"Content-Length: %d\r\n\r\n"%(length))
                                    result += await streamio.write(b"--%s"%self.identifier)

                            # Serialize all parts of the multipart
                            for part in self.parts:
                                    result += await streamio.write(b"\r\n")
                                    result += await part.serialize(self.identifier, streamio)

                            # Terminate multipart request
                            if self.headers[b"Content-Type"] != b"multipart/x-mixed-replace":
                                    result += await streamio.write(b"--")

                    if no_end is False:
                            # Terminate serialize request or response
                            result += await streamio.write(b"\r\n")
                    return result

    class ContentText:
            """ Class that contains a text """
            def __init__(self, text, content_type=None):
                    """ Constructor """
                    self.text = text
                    self.content_type = content_type
                    if content_type is None:
                            self.content_type = b"text/plain"

            async def serialize(self, streamio):
                    """ Serialize text content """
                    result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                    result += await streamio.write(self.text)
                    return result

    class ContentFile:
            """ Class that contains a file """
            def __init__(self, filename, content_type=None, base64=False):
                    """ Constructor """
                    # pylint:disable=global-variable-not-assigned
                    if type(filename) == type([]):
                            self.filenames = filename
                    else:
                            self.filenames = [filename]
                    self.base64 = base64
                    if content_type is None:
                            global MIMES
                            ext = tools.filesystem.splitext(tools.strings.tostrings(self.filenames[0]))[1]
                            self.content_type = MIMES.get(tools.strings.tobytes(ext),b"text/plain")
                    else:
                            self.content_type = content_type

            async def serialize_file(self, filename, streamio):
                    """ Serialize the content of file named filename """
                    result = 0
                    found = False

                    filename = tools.strings.tostrings(filename)

                    # If file existing
                    if tools.filesystem.exists(filename):
                            with open(tools.strings.tostrings(filename), "rb") as f:
                                    found = True
                                    result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                                    if server.stream.Bufferedio.is_enough_memory():
                                            step = 1440*10
                                    else:
                                            step = 512
                                    buf = bytearray(step)
                                    f.seek(0,2)
                                    size = f.tell()
                                    f.seek(0)

                                    if self.base64 and step % 3 != 0:
                                            step = (step//3)*3

                                    length_written = 0

                                    while size > 0:
                                            if size < step:
                                                    buf = bytearray(size)
                                            length = f.readinto(buf)
                                            size -= length
                                            if self.base64:
                                                    length_written += await streamio.write(b2a_base64(buf))
                                            else:
                                                    length_written += await streamio.write(buf)
                                    result += length_written
                    else:
                            tools.logger.syslog("%s file not found"%filename)
                    return result, found

            async def serialize(self, streamio):
                    """ Serialize file """
                    found = False
                    result = 0
                    try:
                            # print("Begin send %s"%tools.strings.tostrings(self.filename))
                            for filename in self.filenames:
                                    r, f = await self.serialize_file(filename, streamio)
                                    result += r
                                    if f:
                                            found = True
                            # print("End send %s"%tools.strings.tostrings(self.filename))
                    except Exception as err:
                            pass
                    if found is False:
                            result = await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                            filenames = b""
                            for filename in self.filenames:
                                    filenames += tools.strings.tobytes(filename) + b" "
                            result += await streamio.write(b"File %s not found"%tools.strings.tobytes(filename))
                    return result

    class ContentBuffer:
            """ Class that contains a buffer """
            def __init__(self, filename, buffer, content_type=None):
                    """ Constructor """
                    # pylint:disable=global-variable-not-assigned
                    self.filename = filename
                    self.buffer = buffer
                    if content_type is None:
                            global MIMES
                            ext = tools.filesystem.splitext(tools.strings.tostrings(filename))[1]
                            self.content_type = MIMES.get(tools.strings.tobytes(ext),b"text/plain")
                    else:
                            self.content_type = content_type

            async def serialize(self, streamio):
                    """ Serialize a buffer """
                    try:
                            b = self.buffer[0]
                            result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                            result += await streamio.write(tools.strings.tobytes(self.buffer))
                    except Exception as err:
                            result = await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                            result += await streamio.write(b"Nothing")
                    return result

    class PartText:
            """ Class that contains a text, used in multipart request or response """
            def __init__(self, name, value):
                    """ Constructor """
                    self.name  = name
                    self.value = value

            async def serialize(self, identifier, streamio):
                    """ Serialize multipart text part """
                    result = await streamio.write(b'Content-Disposition: form-data; name="%s"\r\n'%(self.name))
                    result += await streamio.write(b'Content-Type: text/plain \r\n')
                    result += await streamio.write(b"\r\n%s\r\n"%self.value)
                    result += await streamio.write(b"--%s"%identifier)
                    return result

            async def get_size(self, identifier):
                    """ Get the size of this part """
                    result = await self.serialize(identifier, server.stream.Bytesio())
                    return result

    class PartFile:
            """ Class that contains a file, used in multipart request or response """
            def __init__(self, name, filename, content_type):
                    """ Constructor """
                    self.name = name
                    self.filename = filename
                    self.content_type = content_type

            async def serialize_header(self, identifier, streamio):
                    """ Serialize multi part header of file """
                    result = await streamio.write(b'Content-Disposition: form-data; name="%s"; filename="%s"\r\n'%(self.name, self.filename))
                    result += await streamio.write(b'Content-Type: %s\r\n'%self.content_type)
                    return result

            async def serialize(self, identifier, streamio):
                    """ Serialize multi part file """
                    result = await self.serialize_header(identifier, streamio)
                    with open(tools.strings.tostrings(self.filename),"rb") as file:
                            part = file.read()
                    result += await streamio.write(b"\r\n%s\r\n"%part)
                    result +=  await streamio.write(b"--%s"%identifier)
                    return result

            async def get_size(self, identifier):
                    """ Get the size of multi part file """
                    header_size = await self.serialize_header(identifier, server.stream.Bytesio())
                    file_size = tools.filesystem.filesize((tools.strings.tostrings(self.filename)))
                    return header_size + file_size + 4 + len(identifier) + 2

    class PartBin(PartFile):
            """ Class that contains a binary data, used in multipart request or response """
            def __init__(self, name, filename, binary, content_type):
                    PartFile.__init__(self, name, filename, content_type)
                    self.binary = binary

            async def serialize(self, identifier, streamio):
                    """ Serialize multi part binary data """
                    result = await self.serialize_header(identifier, streamio)
                    result += await streamio.write(b"\r\n%s\r\n"%self.binary)
                    result +=  await streamio.write(b"--%s"%identifier)
                    return result

            async def get_size(self, identifier):
                    """ Get the size of multi part binary data """
                    headerSize = await self.serialize_header(identifier, server.stream.Bytesio())
                    fileSize = len(self.binary)
                    return headerSize + fileSize + 4 + len(identifier) + 2

    class HttpResponse(Http):
            """ Http response send to web browser client """
            def __init__(self, streamio, remoteaddr= b"", port = 0, name = ""):
                    """ Constructor """
                    Http.__init__(self, request=False, remoteaddr=remoteaddr, port=port, name=name)
                    self.chunk_size = 0
                    self.streamio = streamio

            async def send(self, content=None, status=b"200", headers=None):
                    """ Send response to client web browser """
                    if headers is None:
                            headers = {}
                    self.set_content(content)
                    self.set_status(status)
                    if headers is not None:
                            for name, value in headers.items():
                                    self.set_header(name, value)
                    return await self.serialize(self.streamio)

            async def send_error(self, status, content=None):
                    """ Send error to the client web browser """
                    return await self.send(status=status, content=content)

            async def send_not_found(self, err=None):
                    """ Send page not found """
                    if err is None:
                            content = b""
                    elif type(err) == type(b"") or type(err) == type(""):
                            content = tools.strings.tobytes(err)
                    else:
                            content = tools.strings.tobytes(tools.logger.exception(err))
                    return await self.send_error(status=b"404", content=content)

            async def send_ok(self, content=None):
                    """ Send ok to the client web browser """
                    return await self.send_error(status=b"200", content=content)

            async def send_file(self, filename, mime_type=None, headers=None, base64=False):
                    """ Send a file to the client web browser """
                    return await self.send(content=ContentFile(filename, mime_type, base64), status=b"200", headers=headers)

            async def send_buffer(self, filename, buffer, mime_type=None, headers=None):
                    """ Send a file to the client web browser """
                    return await self.send(content=ContentBuffer(filename, buffer, mime_type), status=b"200", headers=headers)

            async def send_page(self, page):
                    """ Send a template page to the client web browser """
                    self.set_content(None)
                    self.set_status(b"200")
                    await self.serialize(self.streamio, page)

            async def receive(self, streamio=None):
                    """ Receive request from client """
                    if streamio is None:
                            streamio = self.streamio
                    await self.unserialize(streamio)

    class HttpRequest(Http):
            """ Http request received from web browser client """
            def __init__(self, streamio, remoteaddr= b"", port = 0, name=""):
                    """ Constructor from http request """
                    Http.__init__(self, request=True, remoteaddr=remoteaddr, port=port, name=name)
                    self.streamio    = streamio

            async def receive(self, streamio=None):
                    """ Receive request from client """
                    if streamio is None:
                            streamio = self.streamio
                    await self.unserialize(streamio)

            async def send(self, streamio=None):
                    """ Send request to server """
                    if streamio is None:
                            streamio = self.streamio
                    await self.serialize(streamio)

            @staticmethod
            def to_html(message):
                    """ Convert message with special characters into html text """
                    result = b""
                    for char in message:
                            if (char >= 0x30 and char <= 0x39) or \
                               (char >= 0x41 and char <= 0x5A) or \
                               (char >= 0x61 and char <= 0x7A):
                                    result += char.to_bytes(1,"big")
                            else:
                                    result += b"&#%d;"%char
                    return result

## Classes

`class ContentBuffer (filename, buffer, content_type=None)`

  Class that contains a buffer

  Constructor

  Expand source code

      class ContentBuffer:
              """ Class that contains a buffer """
              def __init__(self, filename, buffer, content_type=None):
                      """ Constructor """
                      # pylint:disable=global-variable-not-assigned
                      self.filename = filename
                      self.buffer = buffer
                      if content_type is None:
                              global MIMES
                              ext = tools.filesystem.splitext(tools.strings.tostrings(filename))[1]
                              self.content_type = MIMES.get(tools.strings.tobytes(ext),b"text/plain")
                      else:
                              self.content_type = content_type

              async def serialize(self, streamio):
                      """ Serialize a buffer """
                      try:
                              b = self.buffer[0]
                              result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                              result += await streamio.write(tools.strings.tobytes(self.buffer))
                      except Exception as err:
                              result = await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                              result += await streamio.write(b"Nothing")
                      return result

  ### Methods

  `async def serialize(self, streamio)`

    Serialize a buffer

    Expand source code

        async def serialize(self, streamio):
                """ Serialize a buffer """
                try:
                        b = self.buffer[0]
                        result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                        result += await streamio.write(tools.strings.tobytes(self.buffer))
                except Exception as err:
                        result = await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                        result += await streamio.write(b"Nothing")
                return result

`class ContentFile (filename, content_type=None, base64=False)`

  Class that contains a file

  Constructor

  Expand source code

      class ContentFile:
              """ Class that contains a file """
              def __init__(self, filename, content_type=None, base64=False):
                      """ Constructor """
                      # pylint:disable=global-variable-not-assigned
                      if type(filename) == type([]):
                              self.filenames = filename
                      else:
                              self.filenames = [filename]
                      self.base64 = base64
                      if content_type is None:
                              global MIMES
                              ext = tools.filesystem.splitext(tools.strings.tostrings(self.filenames[0]))[1]
                              self.content_type = MIMES.get(tools.strings.tobytes(ext),b"text/plain")
                      else:
                              self.content_type = content_type

              async def serialize_file(self, filename, streamio):
                      """ Serialize the content of file named filename """
                      result = 0
                      found = False

                      filename = tools.strings.tostrings(filename)

                      # If file existing
                      if tools.filesystem.exists(filename):
                              with open(tools.strings.tostrings(filename), "rb") as f:
                                      found = True
                                      result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                                      if server.stream.Bufferedio.is_enough_memory():
                                              step = 1440*10
                                      else:
                                              step = 512
                                      buf = bytearray(step)
                                      f.seek(0,2)
                                      size = f.tell()
                                      f.seek(0)

                                      if self.base64 and step % 3 != 0:
                                              step = (step//3)*3

                                      length_written = 0

                                      while size > 0:
                                              if size < step:
                                                      buf = bytearray(size)
                                              length = f.readinto(buf)
                                              size -= length
                                              if self.base64:
                                                      length_written += await streamio.write(b2a_base64(buf))
                                              else:
                                                      length_written += await streamio.write(buf)
                                      result += length_written
                      else:
                              tools.logger.syslog("%s file not found"%filename)
                      return result, found

              async def serialize(self, streamio):
                      """ Serialize file """
                      found = False
                      result = 0
                      try:
                              # print("Begin send %s"%tools.strings.tostrings(self.filename))
                              for filename in self.filenames:
                                      r, f = await self.serialize_file(filename, streamio)
                                      result += r
                                      if f:
                                              found = True
                              # print("End send %s"%tools.strings.tostrings(self.filename))
                      except Exception as err:
                              pass
                      if found is False:
                              result = await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                              filenames = b""
                              for filename in self.filenames:
                                      filenames += tools.strings.tobytes(filename) + b" "
                              result += await streamio.write(b"File %s not found"%tools.strings.tobytes(filename))
                      return result

  ### Methods

  `async def serialize(self, streamio)`

    Serialize file

    Expand source code

        async def serialize(self, streamio):
                """ Serialize file """
                found = False
                result = 0
                try:
                        # print("Begin send %s"%tools.strings.tostrings(self.filename))
                        for filename in self.filenames:
                                r, f = await self.serialize_file(filename, streamio)
                                result += r
                                if f:
                                        found = True
                        # print("End send %s"%tools.strings.tostrings(self.filename))
                except Exception as err:
                        pass
                if found is False:
                        result = await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                        filenames = b""
                        for filename in self.filenames:
                                filenames += tools.strings.tobytes(filename) + b" "
                        result += await streamio.write(b"File %s not found"%tools.strings.tobytes(filename))
                return result

  `async def serialize_file(self, filename, streamio)`

    Serialize the content of file named filename

    Expand source code

        async def serialize_file(self, filename, streamio):
                """ Serialize the content of file named filename """
                result = 0
                found = False

                filename = tools.strings.tostrings(filename)

                # If file existing
                if tools.filesystem.exists(filename):
                        with open(tools.strings.tostrings(filename), "rb") as f:
                                found = True
                                result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                                if server.stream.Bufferedio.is_enough_memory():
                                        step = 1440*10
                                else:
                                        step = 512
                                buf = bytearray(step)
                                f.seek(0,2)
                                size = f.tell()
                                f.seek(0)

                                if self.base64 and step % 3 != 0:
                                        step = (step//3)*3

                                length_written = 0

                                while size > 0:
                                        if size < step:
                                                buf = bytearray(size)
                                        length = f.readinto(buf)
                                        size -= length
                                        if self.base64:
                                                length_written += await streamio.write(b2a_base64(buf))
                                        else:
                                                length_written += await streamio.write(buf)
                                result += length_written
                else:
                        tools.logger.syslog("%s file not found"%filename)
                return result, found

`class ContentText (text, content_type=None)`

  Class that contains a text

  Constructor

  Expand source code

      class ContentText:
              """ Class that contains a text """
              def __init__(self, text, content_type=None):
                      """ Constructor """
                      self.text = text
                      self.content_type = content_type
                      if content_type is None:
                              self.content_type = b"text/plain"

              async def serialize(self, streamio):
                      """ Serialize text content """
                      result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                      result += await streamio.write(self.text)
                      return result

  ### Methods

  `async def serialize(self, streamio)`

    Serialize text content

    Expand source code

        async def serialize(self, streamio):
                """ Serialize text content """
                result = await streamio.write(b'Content-Type: %s\r\n\r\n'%(self.content_type))
                result += await streamio.write(self.text)
                return result

`class Http (request=True, remoteaddr=b'', port=0, name='')`

  Http request or reponse

  Constructor from http request or response

  Expand source code

      class Http:
              """ Http request or reponse """
              def __init__(self, request = True, remoteaddr= b"", port = 0, name=""):
                      """ Constructor from http request or response """
                      self.port       = port
                      self.name       = name
                      self.remoteaddr = remoteaddr
                      self.path       = b""
                      self.method     = b"POST"
                      self.headers    = collections.OrderedDict()
                      self.params     = collections.OrderedDict()
                      self.cookies    = collections.OrderedDict()
                      self.parts      = []
                      self.status     = 0
                      self.content    = None
                      self.content_file = None
                      self.identifier = None
                      self.request    = request
                      self.chunk_size = 0

              def __del__(self):
                      if self.content_file is not None:
                              tools.filesystem.remove(self.content_file)

              def get_expiration(self, expiration):
                      """ Get cookie expiration date """
                      result = b"; Max-Age=%d"%expiration
                      return result

              def get_cookie(self, name):
                      """ Get cookie value """
                      try:
                              return self.cookies.get(name, None)
                      except:
                              return None

              def set_cookie(self, name, value=None, expiration=None, http_only=False):
                      """ Set cookie """
                      if value is None:
                              if name in self.cookies:
                                      del self.cookies[name]
                      else:
                              self.cookies[name] = (value, expiration, http_only)

              def get_header(self, name):
                      """ Get the http request header """
                      try:
                              return self.headers.get(name, None)
                      except:
                              return None

              def set_header(self, name, value):
                      """ Set the http request header """
                      if value is None:
                              del self.headers[name]
                      else:
                              self.headers[name] = value

              def set_method(self, method):
                      """ Set http request method (POST or GET) """
                      self.method = method

              def get_path(self):
                      """ Get the path of the request or response """
                      return self.path

              def set_path(self, path):
                      """ Define the past of the request or response """
                      self.path = path

              def add_part(self, part):
                      """ Add part of the request. Used for multipart request """
                      self.parts.append(part)

              def get_status(self):
                      """ Get the status value """
                      return self.status

              def set_status(self, status):
                      """ Set the status value """
                      self.status = status

              def set_content(self, content):
                      """ Set the content of the request or response (can be an instance of html template) """
                      if type(content) == type(""):
                              self.content = ContentText(content)
                      else:
                              self.content = content

              def get_content(self):
                      """ Get the content of the request or response """
                      return self.content

              def get_id(self):
                      """ Get the unique identifier of the request or response. Used for multipart request """
                      hash_ = hashlib.sha256()
                      ids = b"%d"%time.time()
                      hash_.update(ids)
                      return hexlify(hash_.digest())[32:]

              async def unserialize(self, streamio):
                      """ Unserialize the request or response in the stream """
                      data = await streamio.readline()
                      if data != b"":
                              urlparser = server.urlparser.UrlParser(data, True)
                              spl = data.split()
                              if len(spl) >= 2:
                                      self.method = urlparser.method
                                      path = spl[1]
                                      if self.request is False:
                                              self.status = path
                                      self.path   = urlparser.path
                                      self.params = urlparser.params
                                      await self.unserialize_headers(streamio)
                              else:
                                      await self.read_content(streamio)

              async def read_content(self, streamio):
                      """ Read the content of http request """
                      if self.headers.get(b"Transfer-Encoding",b"") == b"chunked":
                              length = await streamio.readline()
                              length = eval(tools.strings.tostrings(b"0x%s"%length.strip()))
                              self.chunk_size = length
                              chunk = True
                      else:
                              length = int(self.headers.get(b"Content-Length",b"0"))
                              chunk = False
                      await self.read_data(length, streamio, chunk)

              async def read_data(self, length, streamio, chunk=False):
                      """ Read data with length """
                      # If data small write in memory
                      if length < 4096:
                              if chunk is False or self.content is None:
                                      self.content = b""
                              data = b""
                              while len(data) < length:
                                      data += await streamio.read(length - len(data))
                              self.content += data
                      # Data too big write in file
                      else:
                              self.content_file = "%d.tmp"%id(self)

                              print("Begin upload reception")
                              if chunk is False:
                                      attrib = "wb"
                              else:
                                      attrib = "ab"
                              with open(self.content_file, attrib) as content:
                                      while content.tell() < length:
                                              buffer = await streamio.read(length - content.tell())
                                              content.write(buffer)
                                              length_read = content.tell()
                                              print("  %d%% received"%(length_read*100 // length))
                              print("End upload reception")

              def get_content_filename(self):
                      """ Copy the content into file """
                      if self.content is not None:
                              self.content_file = "%d.tmp"%id(self)
                              with open(self.content_file, "wb") as content:
                                      content.write(self.content)
                              self.content = None
                      return self.content_file

              async def unserialize_headers(self, streamio):
                      """ Extract http header """
                      while True:
                              header = await streamio.readline()
                              if header == b"\r\n":
                                      if self.method == b"POST":
                                              await self.read_content(streamio)
                                              self.params = server.urlparser.UrlParser.parse_params(self.content)
                                      elif self.request is False or self.method == b"PUT":
                                              await self.read_content(streamio)
                                      break
                              name, value = header.split(b":", 1)
                              if name == b"Cookie":
                                      cookies = value.split(b";")
                                      for cookie in cookies:
                                              cookieName,cookieValue=cookie.split(b"=")
                                              self.cookies[cookieName.strip()] = cookieValue.strip()
                              else:
                                      self.headers[name] = value.strip()

              async def serialize(self, streamio, page=None):
                      """ Serialize request or response in the stream """
                      io = server.stream.Bufferedio(streamio)
                      result = await self.serialize_header(io)
                      result += await self.serialize_body(io)
                      if page:
                              await page.write(io)
                      await io.close()
                      return result

              async def serialize_header(self, streamio):
                      """ Serialize the header of http request or response """
                      if self.request:
                              result = await streamio.write(b"%s %s %s\r\n"%(self.method, self.path, b"HTTP/1.1"))
                      else:
                              result = await streamio.write(b"HTTP/1.1 %s NA\r\n"%(self.status))

                      try:
                              createIdentifier = False
                              if len(self.parts) > 0:
                                      createIdentifier = True
                              # If multipart request detected
                              if b"multipart" in self.headers[b"Content-Type"] :
                                      createIdentifier = True
                      except:
                              pass

                      # If identifier required (multipart request)
                      if self.identifier is None and createIdentifier:
                              self.identifier = self.get_id()

                      # Serialize http header
                      for header, value in self.headers.items():
                              if self.identifier is not None:
                                      if header == b"Content-Type":
                                              value += b"; boundary=%s"%self.identifier
                              result += await streamio.write(b"%s: %s\r\n"%(header, value))

                      # Serialize cookies
                      for name, value in self.cookies.items():
                              if self.request:
                                      setget = b""
                              else:
                                      setget = b"Set-"

                              http_only = b""
                              if len(value) >= 3:
                                      if value[2] is True:
                                              http_only = b"; HttpOnly"
                                      if name == b"session":
                                              http_only += b"; Path=/"
                              result += await streamio.write(b"%sCookie: %s=%s%s%s\r\n"%(setget, name, value[0], self.get_expiration(value[1]), http_only))
                      return result

              async def serialize_body(self, streamio):
                      """ Serialize body """
                      result = 0
                      no_end = False
                      # If content existing
                      if self.content is not None:
                              try:
                                      # If content is a bytes string
                                      if type(self.content) == type(b""):
                                              result += await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                                              result += await streamio.write(self.content)
                                      else:
                                              # Serialize object
                                              result += await self.content.serialize(streamio)
                                              no_end = True
                              except Exception as err:
                                      tools.logger.syslog(err)
                                      # Serialize error detected
                                      result += await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                                      result += await streamio.write(tools.strings.tostrings(tools.logger.exception(err)))
                      # If multipart detected
                      elif len(self.parts) > 0:
                              # If the header is a multipart
                              if self.headers[b"Content-Type"] == b"multipart/form-data":
                                      length = 0
                                      # Set the size of identifier
                                      for part in self.parts:
                                              length += 2
                                              length += await part.get_size(self.identifier)
                                      length += len(self.identifier)
                                      length += 6

                                      # Write multipart identifier
                                      result += await streamio.write(b"Content-Length: %d\r\n\r\n"%(length))
                                      result += await streamio.write(b"--%s"%self.identifier)

                              # Serialize all parts of the multipart
                              for part in self.parts:
                                      result += await streamio.write(b"\r\n")
                                      result += await part.serialize(self.identifier, streamio)

                              # Terminate multipart request
                              if self.headers[b"Content-Type"] != b"multipart/x-mixed-replace":
                                      result += await streamio.write(b"--")

                      if no_end is False:
                              # Terminate serialize request or response
                              result += await streamio.write(b"\r\n")
                      return result

  ### Subclasses

  - HttpRequest
  - HttpResponse

  ### Methods

  `def add_part(self, part)`

    Add part of the request. Used for multipart request

    Expand source code

        def add_part(self, part):
                """ Add part of the request. Used for multipart request """
                self.parts.append(part)

  `def get_content(self)`

    Get the content of the request or response

    Expand source code

        def get_content(self):
                """ Get the content of the request or response """
                return self.content

  `def get_content_filename(self)`

    Copy the content into file

    Expand source code

        def get_content_filename(self):
                """ Copy the content into file """
                if self.content is not None:
                        self.content_file = "%d.tmp"%id(self)
                        with open(self.content_file, "wb") as content:
                                content.write(self.content)
                        self.content = None
                return self.content_file

  `def get_cookie(self, name)`

    Get cookie value

    Expand source code

        def get_cookie(self, name):
                """ Get cookie value """
                try:
                        return self.cookies.get(name, None)
                except:
                        return None

  `def get_expiration(self, expiration)`

    Get cookie expiration date

    Expand source code

        def get_expiration(self, expiration):
                """ Get cookie expiration date """
                result = b"; Max-Age=%d"%expiration
                return result

  `def get_header(self, name)`

    Get the http request header

    Expand source code

        def get_header(self, name):
                """ Get the http request header """
                try:
                        return self.headers.get(name, None)
                except:
                        return None

  `def get_id(self)`

    Get the unique identifier of the request or response. Used for multipart request

    Expand source code

        def get_id(self):
                """ Get the unique identifier of the request or response. Used for multipart request """
                hash_ = hashlib.sha256()
                ids = b"%d"%time.time()
                hash_.update(ids)
                return hexlify(hash_.digest())[32:]

  `def get_path(self)`

    Get the path of the request or response

    Expand source code

        def get_path(self):
                """ Get the path of the request or response """
                return self.path

  `def get_status(self)`

    Get the status value

    Expand source code

        def get_status(self):
                """ Get the status value """
                return self.status

  `async def read_content(self, streamio)`

    Read the content of http request

    Expand source code

        async def read_content(self, streamio):
                """ Read the content of http request """
                if self.headers.get(b"Transfer-Encoding",b"") == b"chunked":
                        length = await streamio.readline()
                        length = eval(tools.strings.tostrings(b"0x%s"%length.strip()))
                        self.chunk_size = length
                        chunk = True
                else:
                        length = int(self.headers.get(b"Content-Length",b"0"))
                        chunk = False
                await self.read_data(length, streamio, chunk)

  `async def read_data(self, length, streamio, chunk=False)`

    Read data with length

    Expand source code

        async def read_data(self, length, streamio, chunk=False):
                """ Read data with length """
                # If data small write in memory
                if length < 4096:
                        if chunk is False or self.content is None:
                                self.content = b""
                        data = b""
                        while len(data) < length:
                                data += await streamio.read(length - len(data))
                        self.content += data
                # Data too big write in file
                else:
                        self.content_file = "%d.tmp"%id(self)

                        print("Begin upload reception")
                        if chunk is False:
                                attrib = "wb"
                        else:
                                attrib = "ab"
                        with open(self.content_file, attrib) as content:
                                while content.tell() < length:
                                        buffer = await streamio.read(length - content.tell())
                                        content.write(buffer)
                                        length_read = content.tell()
                                        print("  %d%% received"%(length_read*100 // length))
                        print("End upload reception")

  `async def serialize(self, streamio, page=None)`

    Serialize request or response in the stream

    Expand source code

        async def serialize(self, streamio, page=None):
                """ Serialize request or response in the stream """
                io = server.stream.Bufferedio(streamio)
                result = await self.serialize_header(io)
                result += await self.serialize_body(io)
                if page:
                        await page.write(io)
                await io.close()
                return result

  `async def serialize_body(self, streamio)`

    Serialize body

    Expand source code

        async def serialize_body(self, streamio):
                """ Serialize body """
                result = 0
                no_end = False
                # If content existing
                if self.content is not None:
                        try:
                                # If content is a bytes string
                                if type(self.content) == type(b""):
                                        result += await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                                        result += await streamio.write(self.content)
                                else:
                                        # Serialize object
                                        result += await self.content.serialize(streamio)
                                        no_end = True
                        except Exception as err:
                                tools.logger.syslog(err)
                                # Serialize error detected
                                result += await streamio.write(b'Content-Type: text/plain\r\n\r\n')
                                result += await streamio.write(tools.strings.tostrings(tools.logger.exception(err)))
                # If multipart detected
                elif len(self.parts) > 0:
                        # If the header is a multipart
                        if self.headers[b"Content-Type"] == b"multipart/form-data":
                                length = 0
                                # Set the size of identifier
                                for part in self.parts:
                                        length += 2
                                        length += await part.get_size(self.identifier)
                                length += len(self.identifier)
                                length += 6

                                # Write multipart identifier
                                result += await streamio.write(b"Content-Length: %d\r\n\r\n"%(length))
                                result += await streamio.write(b"--%s"%self.identifier)

                        # Serialize all parts of the multipart
                        for part in self.parts:
                                result += await streamio.write(b"\r\n")
                                result += await part.serialize(self.identifier, streamio)

                        # Terminate multipart request
                        if self.headers[b"Content-Type"] != b"multipart/x-mixed-replace":
                                result += await streamio.write(b"--")

                if no_end is False:
                        # Terminate serialize request or response
                        result += await streamio.write(b"\r\n")
                return result

  `async def serialize_header(self, streamio)`

    Serialize the header of http request or response

    Expand source code

        async def serialize_header(self, streamio):
                """ Serialize the header of http request or response """
                if self.request:
                        result = await streamio.write(b"%s %s %s\r\n"%(self.method, self.path, b"HTTP/1.1"))
                else:
                        result = await streamio.write(b"HTTP/1.1 %s NA\r\n"%(self.status))

                try:
                        createIdentifier = False
                        if len(self.parts) > 0:
                                createIdentifier = True
                        # If multipart request detected
                        if b"multipart" in self.headers[b"Content-Type"] :
                                createIdentifier = True
                except:
                        pass

                # If identifier required (multipart request)
                if self.identifier is None and createIdentifier:
                        self.identifier = self.get_id()

                # Serialize http header
                for header, value in self.headers.items():
                        if self.identifier is not None:
                                if header == b"Content-Type":
                                        value += b"; boundary=%s"%self.identifier
                        result += await streamio.write(b"%s: %s\r\n"%(header, value))

                # Serialize cookies
                for name, value in self.cookies.items():
                        if self.request:
                                setget = b""
                        else:
                                setget = b"Set-"

                        http_only = b""
                        if len(value) >= 3:
                                if value[2] is True:
                                        http_only = b"; HttpOnly"
                                if name == b"session":
                                        http_only += b"; Path=/"
                        result += await streamio.write(b"%sCookie: %s=%s%s%s\r\n"%(setget, name, value[0], self.get_expiration(value[1]), http_only))
                return result

  `def set_content(self, content)`

    Set the content of the request or response (can be an instance of html template)

    Expand source code

        def set_content(self, content):
                """ Set the content of the request or response (can be an instance of html template) """
                if type(content) == type(""):
                        self.content = ContentText(content)
                else:
                        self.content = content

  `def set_cookie(self, name, value=None, expiration=None, http_only=False)`

    Set cookie

    Expand source code

        def set_cookie(self, name, value=None, expiration=None, http_only=False):
                """ Set cookie """
                if value is None:
                        if name in self.cookies:
                                del self.cookies[name]
                else:
                        self.cookies[name] = (value, expiration, http_only)

  `def set_header(self, name, value)`

    Set the http request header

    Expand source code

        def set_header(self, name, value):
                """ Set the http request header """
                if value is None:
                        del self.headers[name]
                else:
                        self.headers[name] = value

  `def set_method(self, method)`

    Set http request method (POST or GET)

    Expand source code

        def set_method(self, method):
                """ Set http request method (POST or GET) """
                self.method = method

  `def set_path(self, path)`

    Define the past of the request or response

    Expand source code

        def set_path(self, path):
                """ Define the past of the request or response """
                self.path = path

  `def set_status(self, status)`

    Set the status value

    Expand source code

        def set_status(self, status):
                """ Set the status value """
                self.status = status

  `async def unserialize(self, streamio)`

    Unserialize the request or response in the stream

    Expand source code

        async def unserialize(self, streamio):
                """ Unserialize the request or response in the stream """
                data = await streamio.readline()
                if data != b"":
                        urlparser = server.urlparser.UrlParser(data, True)
                        spl = data.split()
                        if len(spl) >= 2:
                                self.method = urlparser.method
                                path = spl[1]
                                if self.request is False:
                                        self.status = path
                                self.path   = urlparser.path
                                self.params = urlparser.params
                                await self.unserialize_headers(streamio)
                        else:
                                await self.read_content(streamio)

  `async def unserialize_headers(self, streamio)`

    Extract http header

    Expand source code

        async def unserialize_headers(self, streamio):
                """ Extract http header """
                while True:
                        header = await streamio.readline()
                        if header == b"\r\n":
                                if self.method == b"POST":
                                        await self.read_content(streamio)
                                        self.params = server.urlparser.UrlParser.parse_params(self.content)
                                elif self.request is False or self.method == b"PUT":
                                        await self.read_content(streamio)
                                break
                        name, value = header.split(b":", 1)
                        if name == b"Cookie":
                                cookies = value.split(b";")
                                for cookie in cookies:
                                        cookieName,cookieValue=cookie.split(b"=")
                                        self.cookies[cookieName.strip()] = cookieValue.strip()
                        else:
                                self.headers[name] = value.strip()

`class HttpRequest (streamio, remoteaddr=b'', port=0, name='')`

  Http request received from web browser client

  Constructor from http request

  Expand source code

      class HttpRequest(Http):
              """ Http request received from web browser client """
              def __init__(self, streamio, remoteaddr= b"", port = 0, name=""):
                      """ Constructor from http request """
                      Http.__init__(self, request=True, remoteaddr=remoteaddr, port=port, name=name)
                      self.streamio    = streamio

              async def receive(self, streamio=None):
                      """ Receive request from client """
                      if streamio is None:
                              streamio = self.streamio
                      await self.unserialize(streamio)

              async def send(self, streamio=None):
                      """ Send request to server """
                      if streamio is None:
                              streamio = self.streamio
                      await self.serialize(streamio)

              @staticmethod
              def to_html(message):
                      """ Convert message with special characters into html text """
                      result = b""
                      for char in message:
                              if (char >= 0x30 and char <= 0x39) or \
                                 (char >= 0x41 and char <= 0x5A) or \
                                 (char >= 0x61 and char <= 0x7A):
                                      result += char.to_bytes(1,"big")
                              else:
                                      result += b"&#%d;"%char
                      return result

  ### Ancestors

  - Http

  ### Static methods

  `def to_html(message)`

    Convert message with special characters into html text

    Expand source code

        @staticmethod
        def to_html(message):
                """ Convert message with special characters into html text """
                result = b""
                for char in message:
                        if (char >= 0x30 and char <= 0x39) or \
                           (char >= 0x41 and char <= 0x5A) or \
                           (char >= 0x61 and char <= 0x7A):
                                result += char.to_bytes(1,"big")
                        else:
                                result += b"&#%d;"%char
                return result

  ### Methods

  `async def receive(self, streamio=None)`

    Receive request from client

    Expand source code

        async def receive(self, streamio=None):
                """ Receive request from client """
                if streamio is None:
                        streamio = self.streamio
                await self.unserialize(streamio)

  `async def send(self, streamio=None)`

    Send request to server

    Expand source code

        async def send(self, streamio=None):
                """ Send request to server """
                if streamio is None:
                        streamio = self.streamio
                await self.serialize(streamio)

  ### Inherited members

  - `Http`:
    - `add_part`
    - `get_content`
    - `get_content_filename`
    - `get_cookie`
    - `get_expiration`
    - `get_header`
    - `get_id`
    - `get_path`
    - `get_status`
    - `read_content`
    - `read_data`
    - `serialize`
    - `serialize_body`
    - `serialize_header`
    - `set_content`
    - `set_cookie`
    - `set_header`
    - `set_method`
    - `set_path`
    - `set_status`
    - `unserialize`
    - `unserialize_headers`
`class HttpResponse (streamio, remoteaddr=b'', port=0, name='')`

  Http response send to web browser client

  Constructor

  Expand source code

      class HttpResponse(Http):
              """ Http response send to web browser client """
              def __init__(self, streamio, remoteaddr= b"", port = 0, name = ""):
                      """ Constructor """
                      Http.__init__(self, request=False, remoteaddr=remoteaddr, port=port, name=name)
                      self.chunk_size = 0
                      self.streamio = streamio

              async def send(self, content=None, status=b"200", headers=None):
                      """ Send response to client web browser """
                      if headers is None:
                              headers = {}
                      self.set_content(content)
                      self.set_status(status)
                      if headers is not None:
                              for name, value in headers.items():
                                      self.set_header(name, value)
                      return await self.serialize(self.streamio)

              async def send_error(self, status, content=None):
                      """ Send error to the client web browser """
                      return await self.send(status=status, content=content)

              async def send_not_found(self, err=None):
                      """ Send page not found """
                      if err is None:
                              content = b""
                      elif type(err) == type(b"") or type(err) == type(""):
                              content = tools.strings.tobytes(err)
                      else:
                              content = tools.strings.tobytes(tools.logger.exception(err))
                      return await self.send_error(status=b"404", content=content)

              async def send_ok(self, content=None):
                      """ Send ok to the client web browser """
                      return await self.send_error(status=b"200", content=content)

              async def send_file(self, filename, mime_type=None, headers=None, base64=False):
                      """ Send a file to the client web browser """
                      return await self.send(content=ContentFile(filename, mime_type, base64), status=b"200", headers=headers)

              async def send_buffer(self, filename, buffer, mime_type=None, headers=None):
                      """ Send a file to the client web browser """
                      return await self.send(content=ContentBuffer(filename, buffer, mime_type), status=b"200", headers=headers)

              async def send_page(self, page):
                      """ Send a template page to the client web browser """
                      self.set_content(None)
                      self.set_status(b"200")
                      await self.serialize(self.streamio, page)

              async def receive(self, streamio=None):
                      """ Receive request from client """
                      if streamio is None:
                              streamio = self.streamio
                      await self.unserialize(streamio)

  ### Ancestors

  - Http

  ### Methods

  `async def receive(self, streamio=None)`

    Receive request from client

    Expand source code

        async def receive(self, streamio=None):
                """ Receive request from client """
                if streamio is None:
                        streamio = self.streamio
                await self.unserialize(streamio)

  `async def send(self, content=None, status=b'200', headers=None)`

    Send response to client web browser

    Expand source code

        async def send(self, content=None, status=b"200", headers=None):
                """ Send response to client web browser """
                if headers is None:
                        headers = {}
                self.set_content(content)
                self.set_status(status)
                if headers is not None:
                        for name, value in headers.items():
                                self.set_header(name, value)
                return await self.serialize(self.streamio)

  `async def send_buffer(self, filename, buffer, mime_type=None, headers=None)`

    Send a file to the client web browser

    Expand source code

        async def send_buffer(self, filename, buffer, mime_type=None, headers=None):
                """ Send a file to the client web browser """
                return await self.send(content=ContentBuffer(filename, buffer, mime_type), status=b"200", headers=headers)

  `async def send_error(self, status, content=None)`

    Send error to the client web browser

    Expand source code

        async def send_error(self, status, content=None):
                """ Send error to the client web browser """
                return await self.send(status=status, content=content)

  `async def send_file(self, filename, mime_type=None, headers=None, base64=False)`

    Send a file to the client web browser

    Expand source code

        async def send_file(self, filename, mime_type=None, headers=None, base64=False):
                """ Send a file to the client web browser """
                return await self.send(content=ContentFile(filename, mime_type, base64), status=b"200", headers=headers)

  `async def send_not_found(self, err=None)`

    Send page not found

    Expand source code

        async def send_not_found(self, err=None):
                """ Send page not found """
                if err is None:
                        content = b""
                elif type(err) == type(b"") or type(err) == type(""):
                        content = tools.strings.tobytes(err)
                else:
                        content = tools.strings.tobytes(tools.logger.exception(err))
                return await self.send_error(status=b"404", content=content)

  `async def send_ok(self, content=None)`

    Send ok to the client web browser

    Expand source code

        async def send_ok(self, content=None):
                """ Send ok to the client web browser """
                return await self.send_error(status=b"200", content=content)

  `async def send_page(self, page)`

    Send a template page to the client web browser

    Expand source code

        async def send_page(self, page):
                """ Send a template page to the client web browser """
                self.set_content(None)
                self.set_status(b"200")
                await self.serialize(self.streamio, page)

  ### Inherited members

  - `Http`:
    - `add_part`
    - `get_content`
    - `get_content_filename`
    - `get_cookie`
    - `get_expiration`
    - `get_header`
    - `get_id`
    - `get_path`
    - `get_status`
    - `read_content`
    - `read_data`
    - `serialize`
    - `serialize_body`
    - `serialize_header`
    - `set_content`
    - `set_cookie`
    - `set_header`
    - `set_method`
    - `set_path`
    - `set_status`
    - `unserialize`
    - `unserialize_headers`
`class PartBin (name, filename, binary, content_type)`

  Class that contains a binary data, used in multipart request or response

  Constructor

  Expand source code

      class PartBin(PartFile):
              """ Class that contains a binary data, used in multipart request or response """
              def __init__(self, name, filename, binary, content_type):
                      PartFile.__init__(self, name, filename, content_type)
                      self.binary = binary

              async def serialize(self, identifier, streamio):
                      """ Serialize multi part binary data """
                      result = await self.serialize_header(identifier, streamio)
                      result += await streamio.write(b"\r\n%s\r\n"%self.binary)
                      result +=  await streamio.write(b"--%s"%identifier)
                      return result

              async def get_size(self, identifier):
                      """ Get the size of multi part binary data """
                      headerSize = await self.serialize_header(identifier, server.stream.Bytesio())
                      fileSize = len(self.binary)
                      return headerSize + fileSize + 4 + len(identifier) + 2

  ### Ancestors

  - PartFile

  ### Methods

  `async def get_size(self, identifier)`

    Get the size of multi part binary data

    Expand source code

        async def get_size(self, identifier):
                """ Get the size of multi part binary data """
                headerSize = await self.serialize_header(identifier, server.stream.Bytesio())
                fileSize = len(self.binary)
                return headerSize + fileSize + 4 + len(identifier) + 2

  `async def serialize(self, identifier, streamio)`

    Serialize multi part binary data

    Expand source code

        async def serialize(self, identifier, streamio):
                """ Serialize multi part binary data """
                result = await self.serialize_header(identifier, streamio)
                result += await streamio.write(b"\r\n%s\r\n"%self.binary)
                result +=  await streamio.write(b"--%s"%identifier)
                return result

  ### Inherited members

  - `PartFile`:
    - `serialize_header`
`class PartFile (name, filename, content_type)`

  Class that contains a file, used in multipart request or response

  Constructor

  Expand source code

      class PartFile:
              """ Class that contains a file, used in multipart request or response """
              def __init__(self, name, filename, content_type):
                      """ Constructor """
                      self.name = name
                      self.filename = filename
                      self.content_type = content_type

              async def serialize_header(self, identifier, streamio):
                      """ Serialize multi part header of file """
                      result = await streamio.write(b'Content-Disposition: form-data; name="%s"; filename="%s"\r\n'%(self.name, self.filename))
                      result += await streamio.write(b'Content-Type: %s\r\n'%self.content_type)
                      return result

              async def serialize(self, identifier, streamio):
                      """ Serialize multi part file """
                      result = await self.serialize_header(identifier, streamio)
                      with open(tools.strings.tostrings(self.filename),"rb") as file:
                              part = file.read()
                      result += await streamio.write(b"\r\n%s\r\n"%part)
                      result +=  await streamio.write(b"--%s"%identifier)
                      return result

              async def get_size(self, identifier):
                      """ Get the size of multi part file """
                      header_size = await self.serialize_header(identifier, server.stream.Bytesio())
                      file_size = tools.filesystem.filesize((tools.strings.tostrings(self.filename)))
                      return header_size + file_size + 4 + len(identifier) + 2

  ### Subclasses

  - PartBin

  ### Methods

  `async def get_size(self, identifier)`

    Get the size of multi part file

    Expand source code

        async def get_size(self, identifier):
                """ Get the size of multi part file """
                header_size = await self.serialize_header(identifier, server.stream.Bytesio())
                file_size = tools.filesystem.filesize((tools.strings.tostrings(self.filename)))
                return header_size + file_size + 4 + len(identifier) + 2

  `async def serialize(self, identifier, streamio)`

    Serialize multi part file

    Expand source code

        async def serialize(self, identifier, streamio):
                """ Serialize multi part file """
                result = await self.serialize_header(identifier, streamio)
                with open(tools.strings.tostrings(self.filename),"rb") as file:
                        part = file.read()
                result += await streamio.write(b"\r\n%s\r\n"%part)
                result +=  await streamio.write(b"--%s"%identifier)
                return result

  `async def serialize_header(self, identifier, streamio)`

    Serialize multi part header of file

    Expand source code

        async def serialize_header(self, identifier, streamio):
                """ Serialize multi part header of file """
                result = await streamio.write(b'Content-Disposition: form-data; name="%s"; filename="%s"\r\n'%(self.name, self.filename))
                result += await streamio.write(b'Content-Type: %s\r\n'%self.content_type)
                return result

`class PartText (name, value)`

  Class that contains a text, used in multipart request or response

  Constructor

  Expand source code

      class PartText:
              """ Class that contains a text, used in multipart request or response """
              def __init__(self, name, value):
                      """ Constructor """
                      self.name  = name
                      self.value = value

              async def serialize(self, identifier, streamio):
                      """ Serialize multipart text part """
                      result = await streamio.write(b'Content-Disposition: form-data; name="%s"\r\n'%(self.name))
                      result += await streamio.write(b'Content-Type: text/plain \r\n')
                      result += await streamio.write(b"\r\n%s\r\n"%self.value)
                      result += await streamio.write(b"--%s"%identifier)
                      return result

              async def get_size(self, identifier):
                      """ Get the size of this part """
                      result = await self.serialize(identifier, server.stream.Bytesio())
                      return result

  ### Methods

  `async def get_size(self, identifier)`

    Get the size of this part

    Expand source code

        async def get_size(self, identifier):
                """ Get the size of this part """
                result = await self.serialize(identifier, server.stream.Bytesio())
                return result

  `async def serialize(self, identifier, streamio)`

    Serialize multipart text part

    Expand source code

        async def serialize(self, identifier, streamio):
                """ Serialize multipart text part """
                result = await streamio.write(b'Content-Disposition: form-data; name="%s"\r\n'%(self.name))
                result += await streamio.write(b'Content-Type: text/plain \r\n')
                result += await streamio.write(b"\r\n%s\r\n"%self.value)
                result += await streamio.write(b"--%s"%identifier)
                return result