/
liquid-g
/
liquid-code
Обзор
Документация
Войти
/
liquid-g
/
liquid-code
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop-0.2.0
src/liquidcode/base_server.py
114 строк
4 KB
User
ci: настроен Black и flake8 для автоматического форматирования кода
04 июл 2026, 08:14
04 июл 2026, 08:14
4778ed6
Код
Авторство
О чём код?
""" HTTP-сервер для LiquidCode. Принимает запросы, создаёт HttpRequest, передаёт в Kernel и отправляет ответ. """ import json import logging from http.server import HTTPServer, BaseHTTPRequestHandler from .http import HttpRequest from .kernel import Kernel logger = logging.getLogger(__name__) class LiquidHTTPServer(HTTPServer): """Сервер с доступом к ядру приложения.""" def __init__(self, server_address, handler_class, kernel: Kernel): super().__init__(server_address, handler_class) self.kernel = kernel class RequestHandler(BaseHTTPRequestHandler): """Обработчик HTTP-запросов.""" def do_GET(self): self._handle_request("GET") def do_POST(self): self._handle_request("POST") def do_PUT(self): self._handle_request("PUT") def do_PATCH(self): self._handle_request("PATCH") def do_DELETE(self): self._handle_request("DELETE") def _handle_request(self, method: str) -> None: # 1. Читаем тело и заголовки content_length = int(self.headers.get("Content-Length", 0)) body = self.rfile.read(content_length) if content_length else b"" headers = {k: v for k, v in self.headers.items()} # 2. Создаём HttpRequest request = HttpRequest( path=self.path, method=method, headers=headers, body=body, query_params=None, # парсится внутри HttpRequest ) # 3. Вызываем ядро try: response = self.server.kernel.handle(request) except Exception: logger.exception(f"Необработанное исключение: {method} {self.path}") self._send_json({"error": "Внутренняя ошибка сервера"}, 500, {}) return # 4. Отправляем ответ content = response.get_content() status = response.get_status() headers = response.get_headers() try: if isinstance(content, bytes): # Статические файлы или бинарные данные self.send_response(status) for key, value in headers.items(): self.send_header(key, value) self.end_headers() self.wfile.write(content) else: # JSON-ответ self._send_json(content, status, headers) except (ConnectionAbortedError, BrokenPipeError) as e: logger.debug(f"Соединение разорвано клиентом: {e}") # 5. Вызываем terminate (после отправки ответа) self.server.kernel.terminate(request, response) def _send_json(self, data, status, headers): """Отправляет JSON-ответ.""" try: response_json = json.dumps(data, ensure_ascii=False) except TypeError: logger.error("Данные ответа не сериализуются в JSON") response_json = json.dumps({"error": "Некорректный формат ответа"}) status = 500 try: self.send_response(status) for key, value in headers.items(): self.send_header(key, value) self.send_header("Content-Type", "application/json; charset=utf-8") self.end_headers() self.wfile.write(response_json.encode("utf-8")) except (ConnectionAbortedError, BrokenPipeError) as e: logger.debug(f"Соединение разорвано клиентом при отправке JSON: {e}") def log_message(self, format: str, *args) -> None: """Логирование запросов через стандартный логгер.""" logger.info(f"{self.address_string()} - {format % args}") def create_server(host: str, port: int, kernel: Kernel) -> LiquidHTTPServer: """Создаёт и возвращает настроенный HTTP-сервер.""" server_address = (host, port) return LiquidHTTPServer(server_address, RequestHandler, kernel)