Files
comunidadhll/backend/app/main.py
devRaGonSa 0da8338ba8 Fix
2026-06-05 16:57:25 +02:00

91 lines
3.2 KiB
Python

"""Minimal HTTP entrypoint for the HLL Vietnam backend bootstrap."""
from __future__ import annotations
import json
from datetime import date, datetime
from http import HTTPStatus
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from .config import get_allowed_origins, get_bind_address
from .payloads import build_error_payload
from .routes import resolve_get_payload
class HealthHandler(BaseHTTPRequestHandler):
"""Serve the minimal routes required for the backend bootstrap."""
server_version = "HLLVietnamBackend/0.1"
def do_OPTIONS(self) -> None: # noqa: N802 - BaseHTTPRequestHandler interface
self.send_response(HTTPStatus.NO_CONTENT)
self._send_default_headers()
self.send_header("Access-Control-Allow-Methods", "GET, OPTIONS")
self.send_header("Access-Control-Allow-Headers", "Content-Type")
self.end_headers()
def do_GET(self) -> None: # noqa: N802 - BaseHTTPRequestHandler interface
try:
status, payload = resolve_get_payload(self.path)
except Exception: # noqa: BLE001 - preserve HTTP/CORS response on route failures
self._write_json(
HTTPStatus.INTERNAL_SERVER_ERROR,
build_error_payload("Unexpected backend error"),
)
return
if status is None:
self._write_json(
HTTPStatus.NOT_FOUND,
{"status": "error", "message": "Route not found"},
)
return
self._write_json(status, payload)
def log_message(self, format: str, *args: object) -> None:
# Keep local startup output clean unless future tasks need request logging.
return
def _write_json(self, status: HTTPStatus, payload: dict[str, object]) -> None:
body = json.dumps(payload, default=_json_default).encode("utf-8")
self.send_response(status)
self._send_default_headers(content_length=len(body))
self.end_headers()
self.wfile.write(body)
def _send_default_headers(self, content_length: int | None = None) -> None:
origin = self.headers.get("Origin")
if origin in get_allowed_origins():
self.send_header("Access-Control-Allow-Origin", origin)
self.send_header("Vary", "Origin")
self.send_header("Content-Type", "application/json; charset=utf-8")
if content_length is not None:
self.send_header("Content-Length", str(content_length))
def create_server() -> ThreadingHTTPServer:
"""Build the HTTP server using the package-supported handler and bind settings."""
host, port = get_bind_address()
return ThreadingHTTPServer((host, port), HealthHandler)
def _json_default(value: object) -> str:
"""Serialize PostgreSQL date/time values before they can abort an HTTP response."""
if isinstance(value, (date, datetime)):
return value.isoformat()
raise TypeError(f"Object of type {type(value).__name__} is not JSON serializable")
def run() -> None:
"""Start the local bootstrap server."""
host, port = get_bind_address()
server = create_server()
print(f"HLL Vietnam backend bootstrap listening on http://{host}:{port}")
server.serve_forever()
if __name__ == "__main__":
run()