ariadne/ariadne/utils/errors.py

52 lines
1.5 KiB
Python

from __future__ import annotations
import httpx
def _runtime_error_detail(exc: Exception) -> str | None:
if not isinstance(exc, RuntimeError):
return None
msg = str(exc).strip()
return msg or None
def _http_message_from_payload(payload: object) -> str | None:
if isinstance(payload, dict):
raw = payload.get("errorMessage") or payload.get("error") or payload.get("message")
if isinstance(raw, str) and raw.strip():
return raw.strip()
if isinstance(payload, str) and payload.strip():
return payload.strip()
return None
def _http_response_message(response: httpx.Response) -> str | None:
try:
payload = response.json()
except Exception:
text = (response.text or "").strip()
return text or None
return _http_message_from_payload(payload)
def _http_error_detail(exc: httpx.HTTPStatusError) -> str:
detail = f"http {exc.response.status_code}"
msg = _http_response_message(exc.response)
if not msg:
return detail
msg = " ".join(msg.split())
return f"{detail}: {msg[:200]}"
def safe_error_detail(exc: Exception, fallback: str) -> str:
"""Return a user-safe error message without leaking noisy exception internals."""
runtime_detail = _runtime_error_detail(exc)
if runtime_detail:
return runtime_detail
if isinstance(exc, httpx.HTTPStatusError):
return _http_error_detail(exc)
if isinstance(exc, httpx.TimeoutException):
return "timeout"
return fallback