diff options
Diffstat (limited to 'day7')
| -rw-r--r-- | day7/db/cookies.db | bin | 16384 -> 16384 bytes | |||
| -rw-r--r-- | day7/http_handler.py | 33 | ||||
| -rw-r--r-- | day7/router.py | 33 | ||||
| -rw-r--r-- | day7/templater.py | 6 | ||||
| -rw-r--r-- | day7/utils.py | 8 |
5 files changed, 79 insertions, 1 deletions
diff --git a/day7/db/cookies.db b/day7/db/cookies.db Binary files differindex 89b0f61..d2ece8b 100644 --- a/day7/db/cookies.db +++ b/day7/db/cookies.db diff --git a/day7/http_handler.py b/day7/http_handler.py index 8344d7f..67769d4 100644 --- a/day7/http_handler.py +++ b/day7/http_handler.py @@ -17,6 +17,12 @@ logging.basicConfig(filename=db.get_config_entry('log_path'), level=logging.INFO def log_requests(func): + """ + *Используется как декоратор.* + + Логирует в файл все запросы, приходящие в функцию `process_request`. + """ + def wrapper(address, request, *args, **kwargs): response = func(*args, **kwargs) status = response.split('\n').pop(0).split()[1] @@ -61,6 +67,13 @@ def log_requests(func): @log_requests def process_request(address, request: dict): + """ + *Эта функция логируется с помощью функции* `log_func` + + Проверяется валидность url. Если url валиден, + то запрос отправляется на обработку в `backend.py`. + """ + if validate_url(request['url']): response = run(request) else: @@ -70,6 +83,11 @@ def process_request(address, request: dict): def parse_request(connection): + """ + Принимаем запрос от клиента и тут же парсим заголовки. Если в теле + запроса приходят дополнительные данные, то они тоже обрабатываются. + """ + buffer = b'' request = b'' while not request.endswith(b'\r\n\r\n'): @@ -119,6 +137,13 @@ def get_color(): def handle_connection(connection, address): + """ + Как только к серверу присоединяется какой-то клиент, + то это соединение обрабатывается тут. С помощью `get_request` + принимаются заголовки и отправляются в `process_request`. Ответ + клиенту, полученный из бекэнда, отправляется тут. + """ + try: request = parse_request(connection) except ValueError as e: @@ -137,6 +162,14 @@ def handle_connection(connection, address): def main(): + """ + *Точка входа в программу.* + + Адрес хоста берется из базы данных конфигурации. + Запускает сервер по адресу `host:port`. Также тут + обрабатывается остановка сервера при нажатии `Ctrl+C` + """ + host = db.get_config_entry('host') port = db.get_config_entry('port') diff --git a/day7/router.py b/day7/router.py index c662592..1e3d5af 100644 --- a/day7/router.py +++ b/day7/router.py @@ -6,16 +6,31 @@ from backend import * class Route: + """ + Представляет из себя класс роута. При инициализации принимает допустимые + методы и регулярное выражение. Содержит методы для работы роутинга. + Чтобы созданный путь стал обрабатываться необходимо поместить объект Route в таблицу роутера. + """ + def __init__(self, callback, url_format, methods=None): self.methods = ['GET'] if methods is None else methods self.url_pattern = re.compile(url_format) self.callback = callback - def check_route(self, url, method): + def check_route(self, url, method) -> bool: + """ + По указанным URL и методу проверят подходит ли URL под соответсвующие настройки пути. + """ + match = self.url_pattern.fullmatch(url) return bool(match) and len(match.groups()) == self.url_pattern.groups and method in self.methods def invoke_callback(self, url, method, query): + """ + Как и `check_route` проверяет параметр на валидность, но если он валиден, то + вызывается соответствующий обработчик. + """ + match = self.url_pattern.fullmatch(url) groups = match.groups() @@ -28,6 +43,15 @@ class Route: # url_format - регулярное выражение def route(url_format, methods=None): + """ + *Используется как декоратор.* + + Указание при каком url и методах в запросе должна вызываться декорируемая функция. + При инициализации декоратора надо указать url регулярное выражение и http методы. + В декорируемую функцию передаются параметры query из тела запроса и сматченные группы + из регулярного выражения `url_format`. Добавляет декорируемые функции в дерево роутера. + """ + if methods is None: methods = ['GET'] @@ -52,6 +76,13 @@ def route(url_format, methods=None): def run(request): + """ + Принимает разобранный http-запрос, добавляет новые cookie-данные в базу данных. + Ищет в таблице роутера функцию, которую необходимо вызвать для обработки текущего запроса. + При нахождении такой функции передает ей все необходимые данные о запросе. + Если подходящая функция не была найдена возвращает обработчику статус `404 Not Found`.\ + """ + res = NOT_FOUND, NOT_FOUND for key, value in request['cookies'].items(): diff --git a/day7/templater.py b/day7/templater.py index ac9416e..2963b7e 100644 --- a/day7/templater.py +++ b/day7/templater.py @@ -1,4 +1,10 @@ def render_template(template_name, **kwargs): + """ + Нам постоянно нужно присылать однотипные HTML-странички и для этого пригодится HTML-шаблонизатор, + который может по небольшому количеству изменяемых параметров вернуть готовую страницу. + При каждом вызове шаблон загружается заново, поэтому нет необходимости перезагружать сервер при изменении шаблона. + """ + with open(f'templates/{template_name}.html') as f: data = f.read() diff --git a/day7/utils.py b/day7/utils.py index c17a02d..b00c5c2 100644 --- a/day7/utils.py +++ b/day7/utils.py @@ -15,6 +15,10 @@ FIRST_LINE_PATTERN = re.compile(rf'{"(" + "|".join(HTTP_METHODS) + ")"} {URL_REG def add_text_headers(status, html: str): + """ + Добавляет заголовки к ответной html-странице + """ + return '\r\n'.join([ status, f'Date: {strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime())}', @@ -47,6 +51,10 @@ def parse_cookies(cookies_line: str): def format_cookies(cookies: dict): + """ + Формирование cookie-строки из переданного словаря. + """ + pairs = [] for key, value in cookies: pairs.append(f'{key}={value}') |