Files
bunnycdn-mcp/bunnycdn_mcp/client.py
2026-04-13 10:29:06 +09:00

85 lines
2.8 KiB
Python

"""BunnyCDN REST API client using httpx."""
import httpx
from .config import BUNNY_API_BASE, BUNNY_API_KEY, REQUEST_TIMEOUT, logger
class BunnyClient:
"""Async HTTP client for BunnyCDN API."""
def __init__(self) -> None:
self._base = BUNNY_API_BASE
self._headers = {
"AccessKey": BUNNY_API_KEY,
"Accept": "application/json",
"Content-Type": "application/json",
}
async def get(self, path: str, params: dict | None = None) -> dict | list:
async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT) as c:
resp = await c.get(
f"{self._base}{path}",
headers=self._headers,
params=params,
)
return self._handle(resp)
async def post(self, path: str, json: dict | None = None) -> dict | list | str:
async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT) as c:
resp = await c.post(
f"{self._base}{path}",
headers=self._headers,
json=json,
)
return self._handle(resp)
async def patch(self, path: str, json: dict | None = None) -> dict | list | str:
async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT) as c:
resp = await c.patch(
f"{self._base}{path}",
headers=self._headers,
json=json,
)
return self._handle(resp)
async def put(self, path: str, json: dict | None = None) -> dict | list | str:
async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT) as c:
resp = await c.put(
f"{self._base}{path}",
headers=self._headers,
json=json,
)
return self._handle(resp)
async def delete(self, path: str) -> dict | str:
async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT) as c:
resp = await c.delete(
f"{self._base}{path}",
headers=self._headers,
)
return self._handle(resp)
def _handle(self, resp: httpx.Response) -> dict | list | str:
if resp.status_code == 401:
raise BunnyAPIError("Authentication failed: invalid API key")
if resp.status_code == 404:
raise BunnyAPIError(f"Not found: {resp.url}")
if resp.status_code >= 500:
raise BunnyAPIError(f"Server error {resp.status_code}: {resp.text}")
if resp.status_code >= 400:
raise BunnyAPIError(f"Client error {resp.status_code}: {resp.text}")
if not resp.content:
return ""
try:
return resp.json()
except Exception:
return resp.text
class BunnyAPIError(Exception):
pass
client = BunnyClient()