74 lines
1.8 KiB
Python
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
|