From ce4bfbae1dabb226696629d4fee5398d6d4a7f4d Mon Sep 17 00:00:00 2001 From: Inoland Date: Wed, 8 Oct 2025 16:05:55 +0400 Subject: [PATCH] add http helper --- __init__.py | 6 ++ src/comfyui_ino_nodes/utils/http_helper.py | 77 ++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/comfyui_ino_nodes/utils/http_helper.py diff --git a/__init__.py b/__init__.py index 2b7cc20..ec398fc 100644 --- a/__init__.py +++ b/__init__.py @@ -32,6 +32,8 @@ from .src.comfyui_ino_nodes.s3_helper.s3_download_file_node import InoS3Download from .src.comfyui_ino_nodes.s3_helper.s3_download_folder_node import InoS3DownloadFolder from .src.comfyui_ino_nodes.s3_helper.s3_download_image_node import InoS3DownloadImage +from .src.comfyui_ino_nodes.utils.http_helper import InoHttpCall + NODE_CLASS_MAPPINGS = { "InoParseFilePath": InoParseFilePath, "InoCountFiles": InoCountFiles, @@ -80,6 +82,8 @@ NODE_CLASS_MAPPINGS = { "InoS3DownloadFile": InoS3DownloadFile, "InoS3DownloadFolder": InoS3DownloadFolder, "InoS3DownloadImage": InoS3DownloadImage, + + "InoHttpCall": InoHttpCall, } @@ -130,6 +134,8 @@ NODE_DISPLAY_NAME_MAPPINGS = { "InoS3DownloadFile": "Ino S3 Download File", "InoS3DownloadFolder": "Ino S3 Download Folder", "InoS3DownloadImage": "Ino S3 Download Image", + + "InoHttpCall": "Ino Http Call", } diff --git a/src/comfyui_ino_nodes/utils/http_helper.py b/src/comfyui_ino_nodes/utils/http_helper.py new file mode 100644 index 0000000..3891408 --- /dev/null +++ b/src/comfyui_ino_nodes/utils/http_helper.py @@ -0,0 +1,77 @@ +import httpx +from httpx_retry import AsyncRetryTransport, RetryPolicy + +class InoHttpCall: + """ + + """ + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "enabled": ("BOOLEAN", {"default": True, "label_off": "OFF", "label_on": "ON"}), + "url": ("STRING", {"default": "http://127.0.0.1:3314/health"}), + "request_type": (list(["get", "post", "put", "delete", "patch",]), {}), + "headers": ("STRING", {"default": '{"Connection": "keep-alive"}'}), + "json": ("STRING", {"default": None}) + } + } + + RETURN_TYPES = ("BOOLEAN", "INT", "STRING", "STRING", ) + RETURN_NAMES = ("Success", "StatusCode", "MSG", "Response", ) + + FUNCTION = "function" + CATEGORY = "InoNodes" + + async def function(self, enabled, url, request_type, headers, json): + if not enabled: + return (False, 0, "", "", ) + + timeout = httpx.Timeout(connect=10.0, read=60, write=60, pool=10.0) + limits = httpx.Limits(max_connections=8, max_keepalive_connections=8, keepalive_expiry=120.0) + + exponential_retry = ( + RetryPolicy() + .with_max_retries(10) + .with_min_delay(0.1) + .with_multiplier(2) + .with_retry_on(lambda status_code: status_code >= 500) + ) + + headers = headers + http_conn = httpx.AsyncClient( + timeout=timeout, + limits=limits, + #transport=AsyncRetryTransport(policy=exponential_retry), + headers=headers, + #trust_env=False, + #follow_redirects=False + ) + + try: + if request_type == "get": + resp = await http_conn.get(url) + elif request_type == "post": + resp = await http_conn.post(url, json=json) + elif request_type == "put": + resp = await http_conn.put(url, json=json) + elif request_type == "delete": + resp = await http_conn.delete(url) + elif request_type == "patch": + resp = await http_conn.patch(url, json=json) + else: + resp = await http_conn.get(url) + + resp.raise_for_status() + except httpx.RequestError as exc: + return (False, 0, f"Request error: {exc}", "", ) + except httpx.HTTPStatusError as exc: + return (False, exc.response.status_code, f"HTTP error: {exc.response}", "", ) + + try: + response = resp.json() + except ValueError: + response = resp.text + + return (True, resp.status_code, f"Http call successfull", response, )