예제 #1
0
    def __init__(
        self,
        protocol: ItemType,
        status: ItemType,
        status_msg: ItemType,
        headers: HeadersType = None,
        body: ItemType = None,
    ) -> None:
        """Python object representation of an HTTP/1.x response.

        Args:
            protocol: "<major>.<minor>" numbering scheme to indicate versions of the protocol.
            status: Numberical value designating a specific return value.
            status_msg: Message related to the status code.
            headers: Collection of case-insensitive name followed by a colon (:).
            body: Data associated with the message.
        """

        self._status = Item(status)
        self._status_msg = Item(status_msg)

        super().__init__(protocol, headers, body)

        first_line = self._protocol.raw, self._status.raw, self._status_msg.raw
        self._first_line = Item(b"%b %b %b" % first_line)
예제 #2
0
    def __init__(
        self,
        method: ItemType,
        target: ItemType,
        protocol: HeadersType,
        headers: ItemType = None,
        body: ItemType = None,
    ) -> None:
        """Python object representation of an HTTP/1.x request."

        Args:
            method: Indicates the desired action on the server's resource.
            target: Resource location in the server for which the client is requesting.
            protocol: "<major>.<minor>" numbering scheme to indicate versions of the protocol.
            headers: Collection of case-insensitive name followed by a colon (:).
            body: Data associated with the message.
        """

        self._method = Item(method)
        self._target = Item(target)

        super().__init__(protocol, headers, body)

        first_line = (self._method.raw, self._target.raw, self._protocol.raw)
        self._first_line = Item(b"%b %b %b" % first_line)
예제 #3
0
    def __setattr__(self, key: str, value: str) -> None:
        """Sets a new attribute inside Headers.

        Notes:
            If "_" is present in the key it gets replaced with "-". This is so, example,
            "headers.User_Agent" is equivalent to "headers['User-Agent']".
        """

        key_mod = key.replace("_", "-").encode(ENCODE)
        self[Item(key_mod)] = Item(value)
예제 #4
0
    def __iadd__(self, other: Union[dict, "Headers"]) -> "Headers":
        """Adds current headers with passed other and returns self.

        Args:
            other: Headers or dictionary to be added.

        Returns:
            Headers: Self after addition of other to itself.
        """

        self._check(other)

        itemized_values = {Item(k): Item(v) for k, v in other.items()}
        self.update(itemized_values)
        return self
예제 #5
0
    def __init__(self, headers: HeadersType = None) -> None:
        """Initializes the Headers object.

        Args:
            value: Dictionary, headers, or None object that represents the headers.
        """

        if headers is None:
            headers = {}

        self._check(headers)

        if isinstance(headers, dict):
            for key, value in headers.items():
                self[Item(key)] = Item(value)

        super().__init__()
예제 #6
0
    def _compile_first_line(self) -> None:
        """Compiles the first line of the message.

        Notes:
            Sets self._first_line to self.protocol, self.status, self.status_msg.
        """
        first_line = self._protocol.raw, self._status.raw, self._status_msg.raw
        self._first_line = Item(b"%b %b %b" % first_line)
예제 #7
0
    def _compile_first_line(self) -> None:
        """Compiles the first line of the message.

        Notes:
            Sets self._first_line to self.protocol, self.method, self.target.
        """
        first_line = (self._method.raw, self._target.raw, self._protocol.raw)
        self._first_line = Item(b"%b %b %b" % first_line)
예제 #8
0
    def __add__(self, other: Union[dict, "Headers"]) -> "Headers":
        """Adds item with passed other and returns new Headers.

        Args:
            other: Headers or dictionary to be added.

        Returns:
            Headers: New resulting Headers object.
        """

        self._check(other)

        if isinstance(other, Headers):
            current = self.copy()
            current.update(other)
            return Headers(current)
        elif isinstance(other, dict):
            itemized_values = {Item(k): Item(v) for k, v in other.items()}
            copy = self.copy()
            copy.update(itemized_values)
            return copy
예제 #9
0
    def __init__(
        self, protocol: ItemType, headers: HeadersType = None, body: ItemType = None
    ) -> None:
        """Initializes an HTTP Message.

        Args:
            protocol: "<major>.<minor>" numbering scheme to indicate versions of the protocol.
            headers: Collection of case-insensitive name followed by a colon (:).
            body: Data associated with the message.
        """
        self._first_line = None
        self._protocol = Item(protocol)

        if isinstance(headers, Headers):
            self._headers = headers
        elif headers is None:
            self._headers = Headers()
        else:
            self._headers = Headers(headers)

        self._body = Item(body)
예제 #10
0
    def parse(cls: Union["Message", "Response", "Request"], message: Any) -> None:
        """Parses a raw HTTP message (in bytes or string) to an object instance of class 'cls'.

        Args:
            message: The primative or object to convert into a Request or Response object.

        Returns:
            An initialized object of class 'cls'.
        """

        if isinstance(cls, Message):
            err = "You can only use .parse() with either the Request or Response class."
            raise ValueError(err)

        if not isinstance(message, Item):
            message = Item(message)

        first_line = b""
        headers = Headers({})
        body = b""

        top_frame = True
        for index, line in enumerate(message.raw.splitlines()):
            if line == b"":
                top_frame = False

            if top_frame:
                if index == 0:
                    first_line = line
                elif b":" in line:
                    key, value = line.split(b":", 1)
                    headers += {key: value.lstrip(b" ")}
            else:
                body += line

        args = (*first_line.split(b" "), headers, body)

        try:
            return cls(*args)
        except TypeError as error:  # pragma: no cover
            err = "Error parsing the message due to {}.".format(error)
            raise TypeError(err) from error
예제 #11
0
 def status_msg(self, value: ItemType) -> None:
     self._status_msg = Item(value)
예제 #12
0
 def status(self, value: ItemType) -> None:
     self._status = Item(value)
예제 #13
0
 def target(self, value: ItemType) -> None:
     self._target = Item(value)
예제 #14
0
 def method(self, value: ItemType) -> None:
     self._method = Item(value)
예제 #15
0
 def body(self, value: ItemType) -> None:
     self._body = Item(value)
예제 #16
0
 def protocol(self, value: ItemType) -> None:
     self._protocol = Item(value)