"""SSRF-guarded, multi-method HTTP client exposed to plugins (SPEC ยง10.6). ``sdk.http_get`` covers simple GETs; heavy plugins that speak CalDAV/CardDAV need other verbs (PROPFIND/REPORT/PUT/DELETE) with request bodies and basic auth. This facade routes all of them through the same SSRF policy (HTTPS-only, public host, no off-domain redirects, size cap) and returns status + headers + body. """ from __future__ import annotations from app.accounts.ssrf import GuardedResponse, guarded_request class PluginHttp: async def request( self, method: str, url: str, *, headers: dict[str, str] | None = None, content: bytes | str | None = None, auth: tuple[str, str] | None = None, ) -> GuardedResponse: return await guarded_request( method, url, headers=headers, content=content, auth=auth ) async def get(self, url: str, **kw: object) -> GuardedResponse: return await self.request("GET", url, **kw) # type: ignore[arg-type] async def put(self, url: str, **kw: object) -> GuardedResponse: return await self.request("PUT", url, **kw) # type: ignore[arg-type] async def delete(self, url: str, **kw: object) -> GuardedResponse: return await self.request("DELETE", url, **kw) # type: ignore[arg-type] async def propfind(self, url: str, **kw: object) -> GuardedResponse: return await self.request("PROPFIND", url, **kw) # type: ignore[arg-type] async def report(self, url: str, **kw: object) -> GuardedResponse: return await self.request("REPORT", url, **kw) # type: ignore[arg-type]