Skip to content

Commit

Permalink
add post method for requests with large body
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor authored and Igor committed Sep 2, 2024
1 parent 76551fd commit d778a73
Showing 1 changed file with 40 additions and 17 deletions.
57 changes: 40 additions & 17 deletions bitrix24/bitrix24.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
from typing import Any, Dict
from urllib.parse import urlparse

from aiohttp import ClientSession, TCPConnector
from aiohttp import ClientSession, TCPConnector, hdrs
from aiohttp.web_exceptions import HTTPMethodNotAllowed

from .exceptions import BitrixError

Expand Down Expand Up @@ -95,15 +96,25 @@ def _prepare_params(self, params: Dict[str, Any], prev: str = "") -> str:
ret += "{0}={1}&".format(key, value)
return ret

async def request(self, method: str, params: str = None) -> Dict[str, Any]:
async def request(self, http_method: str, method: str, params: str = None) -> Dict[str, Any]:
http_method = http_method.upper().strip()

ssl_context = ssl.create_default_context()
if not self._verify_ssl:
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE

async with ClientSession(connector=TCPConnector(ssl=ssl_context)) as session:
async with session.get(
f"{self._domain}/{method}.json", params=params, timeout=self._timeout
) as resp:
url = f"{self._domain}/{method}.json"
if http_method == hdrs.METH_GET:
req = session.get(url, params=params, timeout=self._timeout)
elif http_method == hdrs.METH_POST:
req = session.post(url, data=params, timeout=self._timeout)
else:
allowed_methods = {hdrs.METH_GET, hdrs.METH_POST}
raise HTTPMethodNotAllowed(http_method, allowed_methods)

async with req as resp:
if resp.status not in [200, 201]:
raise BitrixError(f"HTTP error: {resp.status}")
response = await resp.json()
Expand All @@ -115,22 +126,27 @@ async def request(self, method: str, params: str = None) -> Dict[str, Any]:
return response

async def _call(
self, method: str, params: Dict[str, Any] = None, start: int = 0
self,
http_method: str,
method: str,
params: Dict[str, Any] = None,
start: int = 0
) -> Dict[str, Any]:
"""Async call a REST method with specified parameters.
Parameters
----------
method (str): REST method name
params (dict): Optional arguments which will be converted to a POST request string
start (int): Offset for pagination
http_method (str): HTTP method name
method (str): REST method name
params (dict): Optional arguments which will be converted to a POST request string
start (int): Offset for pagination
"""
if params is None:
params = {}
params["start"] = start

payload = self._prepare_params(params)
res = await self.request(method, payload)
res = await self.request(http_method, method, payload)

if "next" in res and not start and self._fetch_all_pages:
if res["total"] % 50 == 0:
Expand All @@ -139,7 +155,7 @@ async def _call(
count_tasks = res["total"] // 50

tasks = [
self._call(method, params, (s + 1) * 50) for s in range(count_tasks)
self._call(http_method, method, params, (s + 1) * 50) for s in range(count_tasks)
]
items = await asyncio.gather(*tasks)
if type(res["result"]) is not dict:
Expand All @@ -150,13 +166,20 @@ async def _call(
res["result"][key] += item[key]
return res["result"]

def callMethod(self, method: str, params: Dict[str, Any] = None, **kwargs) -> Dict[str, Any]:
def callMethod(
self,
method: str,
params: Dict[str, Any] = None,
http_method: str = hdrs.METH_GET,
**kwargs,
) -> Dict[str, Any]:
"""Call a REST method with specified parameters.
Parameters
----------
method (str): REST method name
params (dict): Optional arguments which will be converted to a POST request string
method (str): REST method name
params (dict): Optional arguments which will be converted to a POST request string
http_method (str): HTTP method name (GET, POST, etc.)
Returns
-------
Expand All @@ -169,7 +192,7 @@ def callMethod(self, method: str, params: Dict[str, Any] = None, **kwargs) -> Di
raise BitrixError("Wrong method name", 400)

try:
loop = asyncio.get_running_loop()
asyncio.get_running_loop()
except RuntimeError:
warnings.warn(
"You are using `callMethod` method in a synchronous way. "
Expand All @@ -180,9 +203,9 @@ def callMethod(self, method: str, params: Dict[str, Any] = None, **kwargs) -> Di
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
result = loop.run_until_complete(self._call(method, params or kwargs))
result = loop.run_until_complete(self._call(http_method, method, params or kwargs))
finally:
loop.close()
else:
result = asyncio.ensure_future(self._call(method, params or kwargs))
result = asyncio.ensure_future(self._call(http_method, method, params or kwargs))
return result

0 comments on commit d778a73

Please sign in to comment.