from __future__ import annotations from typing import Any import httpx from flask import jsonify, request from . import settings class AriadneError(Exception): def __init__(self, message: str, status_code: int = 502) -> None: super().__init__(message) self.status_code = status_code def enabled() -> bool: return bool(settings.ARIADNE_URL) def _auth_headers() -> dict[str, str]: header = request.headers.get("Authorization", "").strip() return {"Authorization": header} if header else {} def _url(path: str) -> str: base = settings.ARIADNE_URL.rstrip("/") suffix = path.lstrip("/") return f"{base}/{suffix}" if suffix else base def request_raw( method: str, path: str, *, payload: Any | None = None, params: dict[str, Any] | None = None, ) -> httpx.Response: if not enabled(): raise AriadneError("ariadne not configured", 503) try: with httpx.Client(timeout=settings.ARIADNE_TIMEOUT_SEC) as client: return client.request( method, _url(path), headers=_auth_headers(), json=payload, params=params, ) except httpx.RequestError as exc: raise AriadneError("ariadne unavailable", 502) from exc def proxy( method: str, path: str, *, payload: Any | None = None, params: dict[str, Any] | None = None, ) -> tuple[Any, int]: try: resp = request_raw(method, path, payload=payload, params=params) except AriadneError as exc: return jsonify({"error": str(exc)}), exc.status_code try: data = resp.json() except ValueError: detail = resp.text.strip() data = {"error": detail or "upstream error"} return jsonify(data), resp.status_code