from json import dumps from ssl import SSLContext, create_default_context from urllib.error import HTTPError from urllib.request import Request, urlopen from urllib.parse import urlencode def request( url: str, method: str, query_params: dict[str, str] | None = None, data: dict[str, str] | None = None, headers: dict[str, str] | None = None, ) -> str: try: with urlopen( Request( url + ( ("?" + "&".join(f"{k}={v}" for k, v in query_params.items())) if query_params else "" ), dumps(data).encode() if data else None, headers=headers or {}, method=method, ), context=create_default_context(), ) as resp: return resp.read().decode("utf-8") except HTTPError as e: e.add_note(e.url) raise def get( url: str, query_params: dict[str, str] | None = None, headers: dict[str, str] | None = None, ) -> str: return request(url, "GET", query_params=query_params, headers=headers) def post( url: str, data: dict[str, str] | None = None, headers: dict[str, str] | None = None, ) -> str: return request(url, "POST", data=data, headers=headers) def put( url: str, data: dict[str, str] | None = None, headers: dict[str, str] | None = None, ) -> str: return request(url, "PUT", data=data, headers=headers) def delete( url: str, headers: dict[str, str] | None = None, ) -> str: return request(url, "DELETE", headers=headers)