Files
bunnycdn-mcp/bunnycdn_mcp/client.py
kappa 1edc063cd9
All checks were successful
CI / build (push) Successful in 2m6s
fix: Shield tools → Shield Zone API (/shield/shield-zone), client.py에 put 추가
구 API(Pull Zone ShieldDDosProtectionEnabled 필드)는 읽기 전용이라 Shield 설정 변경 불가.
새 Shield Zone API: bunny_shield_list, bunny_shield_status(by shieldZoneId),
bunny_shield_create, bunny_shield_update(PUT), bunny_waf_rules, bunny_waf_logs.
waf_logs 엔드포인트도 /shield/event-logs/{shieldZoneId}로 수정.
2026-04-13 10:03:14 +09:00

76 lines
2.4 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 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()