core/dev.py

144 lines
6.2 KiB
Python
Raw Permalink Normal View History

2025-06-16 17:20:23 +00:00
import argparse
2025-05-19 08:25:41 +00:00
import subprocess
from pathlib import Path
from typing import Optional
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
from granian import Granian
from granian.constants import Interfaces
2025-05-19 08:25:41 +00:00
2025-05-29 09:37:39 +00:00
from utils.logger import root_logger as logger
2025-05-19 08:25:41 +00:00
def check_mkcert_installed() -> Optional[bool]:
2025-05-19 08:25:41 +00:00
"""
Проверяет, установлен ли инструмент mkcert в системе
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
Returns:
bool: True если mkcert установлен, иначе False
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
>>> check_mkcert_installed() # doctest: +SKIP
True
"""
try:
subprocess.run(["mkcert", "-version"], capture_output=True, check=False)
2025-05-19 08:25:41 +00:00
return True
except FileNotFoundError:
return False
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
def generate_certificates(domain="localhost", cert_file="localhost.pem", key_file="localhost-key.pem"):
"""
Генерирует сертификаты с использованием mkcert
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
Args:
domain: Домен для сертификата
cert_file: Имя файла сертификата
key_file: Имя файла ключа
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
Returns:
tuple: (cert_file, key_file) пути к созданным файлам
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
>>> generate_certificates() # doctest: +SKIP
('localhost.pem', 'localhost-key.pem')
"""
# Проверяем, существуют ли сертификаты
2025-06-16 17:20:23 +00:00
if Path(cert_file).exists() and Path(key_file).exists():
2025-05-19 08:25:41 +00:00
logger.info(f"Сертификаты уже существуют: {cert_file}, {key_file}")
return cert_file, key_file
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
# Проверяем, установлен ли mkcert
if not check_mkcert_installed():
logger.error("mkcert не установлен. Установите mkcert с помощью команды:")
logger.error(" macOS: brew install mkcert")
logger.error(" Linux: apt install mkcert или эквивалент для вашего дистрибутива")
logger.error(" Windows: choco install mkcert")
logger.error("После установки выполните: mkcert -install")
return None, None
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
try:
# Запускаем mkcert для создания сертификата
logger.info(f"Создание сертификатов для {domain} с помощью mkcert...")
result = subprocess.run(
["mkcert", "-cert-file", cert_file, "-key-file", key_file, domain],
capture_output=True,
2025-05-29 09:37:39 +00:00
text=True,
check=False,
2025-05-19 08:25:41 +00:00
)
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
if result.returncode != 0:
logger.error(f"Ошибка при создании сертификатов: {result.stderr}")
return None, None
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
logger.info(f"Сертификаты созданы: {cert_file}, {key_file}")
return cert_file, key_file
except Exception as e:
logger.error(f"Не удалось создать сертификаты: {e!s}")
2025-05-19 08:25:41 +00:00
return None, None
2025-05-29 09:37:39 +00:00
2025-06-16 17:20:23 +00:00
def run_server(host="localhost", port=8000, use_https=False, workers=1, domain="localhost") -> None:
2025-05-19 08:25:41 +00:00
"""
Запускает сервер Granian с поддержкой HTTPS при необходимости
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
Args:
host: Хост для запуска сервера
port: Порт для запуска сервера
use_https: Флаг использования HTTPS
workers: Количество рабочих процессов
2025-06-16 17:20:23 +00:00
domain: Домен для сертификата
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
>>> run_server(use_https=True) # doctest: +SKIP
"""
# Проблема с многопроцессорным режимом - не поддерживает локальные объекты приложений
# Всегда запускаем в режиме одного процесса для отладки
if workers > 1:
logger.warning("Многопроцессорный режим может вызвать проблемы сериализации приложения. Использую 1 процесс.")
workers = 1
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
try:
2025-06-16 17:20:23 +00:00
if use_https:
# Генерируем сертификаты с помощью mkcert
cert_file, key_file = generate_certificates(domain=domain)
if not cert_file or not key_file:
logger.error("Не удалось сгенерировать сертификаты для HTTPS")
return
logger.info(f"Запуск HTTPS сервера на https://{host}:{port} с использованием Granian")
# Запускаем Granian сервер с явным указанием ASGI
server = Granian(
address=host,
port=port,
workers=workers,
interface=Interfaces.ASGI,
target="main:app",
ssl_cert=Path(cert_file),
ssl_key=Path(key_file),
)
else:
logger.info(f"Запуск HTTP сервера на http://{host}:{port} с использованием Granian")
server = Granian(
address=host,
port=port,
workers=workers,
interface=Interfaces.ASGI,
target="main:app",
)
2025-05-19 08:25:41 +00:00
server.serve()
except Exception as e:
2025-06-16 17:20:23 +00:00
# В случае проблем с Granian, логируем ошибку
logger.error(f"Ошибка при запуске Granian: {e!s}")
2025-05-19 08:25:41 +00:00
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
if __name__ == "__main__":
2025-06-16 17:20:23 +00:00
parser = argparse.ArgumentParser(description="Запуск сервера разработки с поддержкой HTTPS")
parser.add_argument("--https", action="store_true", help="Использовать HTTPS")
parser.add_argument("--workers", type=int, default=1, help="Количество рабочих процессов")
parser.add_argument("--domain", type=str, default="localhost", help="Домен для сертификата")
parser.add_argument("--port", type=int, default=8000, help="Порт для запуска сервера")
parser.add_argument("--host", type=str, default="localhost", help="Хост для запуска сервера")
args = parser.parse_args()
run_server(host=args.host, port=args.port, use_https=args.https, workers=args.workers, domain=args.domain)