78 lines
2.5 KiB
Python
78 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from typing import Any, Self
|
|
from Utils.Check import Check
|
|
from Utils.Patterns import RE
|
|
from Utils.Utils import Utils
|
|
from re import Match as REMatch
|
|
from socket import socket as Socket
|
|
|
|
class RequestModel:
|
|
|
|
def __init__(self:Self, data:str, inputs:dict[str, Any|None]) -> None:
|
|
|
|
header:list[str]
|
|
line:str
|
|
|
|
self.address:str = inputs.get("address")
|
|
self.port:int = inputs.get("port")
|
|
self.client:Socket = inputs.get("client")
|
|
self.public_path:str = inputs.get("public_path")
|
|
self.index_files:list[str] = inputs.get("index_files")
|
|
self.method:str
|
|
self.request:str
|
|
self.protocol:str
|
|
self.protocol_version:str
|
|
self.variables_get:dict[str, str] = {}
|
|
self.variables_post:dict[str, str] = {}
|
|
self.variables_request:dict[str, str] = {}
|
|
self.headers:dict[str, str] = {}
|
|
self.body:str|None
|
|
|
|
header, self.body = (lambda header, body:(
|
|
RE.NEW_LINE.split(str(header).strip()), body
|
|
))(*RE.HTTP_BLOCKS.match(data).groups())
|
|
|
|
(
|
|
self.method,
|
|
self.request,
|
|
self.variables_get,
|
|
self.protocol,
|
|
self.protocol_version
|
|
) = (lambda method, request, variables, protocol, protocol_version:(
|
|
str(method).lower(),
|
|
request,
|
|
self.parse_variables(variables),
|
|
protocol,
|
|
protocol_version
|
|
))(*RE.HTTP_REQUEST.match(header[0]).groups())
|
|
|
|
for line in header[1:]:
|
|
|
|
key:str
|
|
value:str
|
|
|
|
key, value = RE.HEADER_LINE.match(line).groups()
|
|
|
|
self.headers[key.strip().lower()] = value.strip()
|
|
|
|
self.variables_post = self.parse_variables(self.body or "")
|
|
|
|
@staticmethod
|
|
def parse_variables_set(data:str) -> dict[str, str]:
|
|
|
|
json:dict[str, str]|list[Any|None]|tuple[Any|None]|None = Utils.json_decode(data)
|
|
|
|
if Check.is_dictionary(json):
|
|
return json
|
|
return {key : value for key, value in RE.URI_VARIABLES.findall(data) or []}
|
|
|
|
@classmethod
|
|
def parse_variables(cls:type[Self], data:str|None) -> dict[str, str]:
|
|
return cls.parse_variables_set(
|
|
Utils.base64_decode(data) or data
|
|
) if data else {}
|
|
|
|
def set_request_variables(self:Self, matches:REMatch, keys:tuple[str]) -> None:
|
|
self.variables_request = {keys[i] : value for i, value in enumerate(matches.groups()[1:])} |