All checks were successful
CI / build (push) Successful in 2m6s
구 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}로 수정.
76 lines
2.4 KiB
Python
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()
|