74 lines
1.8 KiB
Python

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