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

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

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

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

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

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

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

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

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

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

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