core/dev.py

123 lines
5.0 KiB
Python
Raw Normal View History

2025-05-19 08:25:41 +00:00
import os
import subprocess
from pathlib import Path
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
from granian import Granian
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():
"""
Проверяет, установлен ли инструмент 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"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
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')
"""
# Проверяем, существуют ли сертификаты
if os.path.exists(cert_file) and os.path.exists(key_file):
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],
2025-05-29 09:37:39 +00:00
stdout=subprocess.PIPE,
2025-05-19 08:25:41 +00:00
stderr=subprocess.PIPE,
2025-05-29 09:37:39 +00:00
text=True,
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"Не удалось создать сертификаты: {str(e)}")
return None, None
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
def run_server(host="0.0.0.0", port=8000, workers=1):
"""
Запускает сервер 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-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
# При проблемах с ASGI можно попробовать использовать Uvicorn как запасной вариант
try:
# Генерируем сертификаты с помощью mkcert
cert_file, key_file = generate_certificates()
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
if not cert_file or not key_file:
logger.error("Не удалось сгенерировать сертификаты для HTTPS")
return
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
logger.info(f"Запуск HTTPS сервера на https://{host}:{port} с использованием Granian")
# Запускаем Granian сервер с явным указанием ASGI
server = Granian(
address=host,
port=port,
workers=workers,
interface="asgi",
2025-05-29 09:37:39 +00:00
target="main:app",
2025-05-19 08:25:41 +00:00
ssl_cert=Path(cert_file),
ssl_key=Path(key_file),
)
server.serve()
except Exception as e:
# В случае проблем с Granian, пробуем запустить через Uvicorn
logger.error(f"Ошибка при запуске Granian: {str(e)}")
2025-05-29 09:37:39 +00:00
2025-05-19 08:25:41 +00:00
if __name__ == "__main__":
2025-05-29 09:37:39 +00:00
run_server()