42 lines
1.6 KiB
Python
42 lines
1.6 KiB
Python
"""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]
|