""" HTTP请求组件类 提供 GET请求组件和POST请求组件 """ import logging from typing import Dict, Any from services.execution.task_context import TaskContext from .base import BlockHandler, register_handler from utils.logger import get_logger from .model.block_name import HttpRequestBlockName # 获取日志记录器 logger = get_logger("services.execution.handlers.htttp_request") @register_handler(HttpRequestBlockName.GET) class HttpGetBlockHandler(BlockHandler): """HTTP GET请求处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行HTTP GET请求""" import aiohttp import asyncio import json try: # 获取请求参数 url = input_params.get("url") # 处理headers参数 headers = {} header_param = input_params.get("header", {}) # 如果header是字符串,尝试解析JSON if isinstance(header_param, str): try: header_data = json.loads(header_param) # 检查解析后的数据是否为列表格式 [{"key0":"value0", "value0":"value"}, ...] if isinstance(header_data, list): for item in header_data: # 寻找以key开头的键,如key0, key1等 for key in [k for k in item if k.startswith('key')]: if key in item and item[key]: # 对应的value键应该是value0, value1等 value_key = 'value' + key[3:] if value_key in item and item[value_key]: headers[item[key]] = item[value_key] # 如果是字典格式,直接使用 elif isinstance(header_data, dict): headers = header_data except json.JSONDecodeError: logger.warning(f"无法解析headers JSON: {header_param}") elif isinstance(header_param, dict): headers = header_param retry = input_params.get("retry", False) # 确保retry_times为整数 retry_times = input_params.get("retryTimes", 3) if isinstance(retry_times, str): try: retry_times = int(retry_times) except ValueError: retry_times = 3 # 确保retry_interval为整数 retry_interval = input_params.get("retryInterval", 1000) if isinstance(retry_interval, str): try: retry_interval = int(retry_interval) except ValueError: retry_interval = 1000 if not url: result = { "success": False, "message": "缺少请求URL" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 执行HTTP请求 attempt = 0 max_attempts = 1 if not retry else retry_times + 1 while attempt < max_attempts: try: async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: # 读取响应内容 response_text = await response.text() # 尝试解析JSON try: response_json = await response.json() context.set_variable("response", response_json) except: # 不是有效的JSON,保存为文本 context.set_variable("response", response_text) result = { "success": True, "message": f"HTTP GET请求成功,状态码: {response.status}", } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: attempt += 1 if attempt >= max_attempts: raise # 重试间隔 await asyncio.sleep(retry_interval / 1000) except Exception as e: result = { "success": False, "message": f"HTTP GET请求失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result # HTTP POST请求处理器 @register_handler(HttpRequestBlockName.POST) class HttpPostBlockHandler(BlockHandler): """HTTP POST请求处理器""" async def execute( self, block: Dict[str, Any], input_params: Dict[str, Any], context: TaskContext ) -> Dict[str, Any]: """执行HTTP POST请求""" import aiohttp import asyncio import json try: # 获取请求参数 url = input_params.get("url") params = input_params.get("param", "{}") # 处理headers参数 headers = {} header_param = input_params.get("header", {}) # 如果header是字符串,尝试解析JSON if isinstance(header_param, str): try: header_data = json.loads(header_param) # 检查解析后的数据是否为列表格式 [{"key0":"value0", "value0":"value"}, ...] if isinstance(header_data, list): for item in header_data: # 寻找以key开头的键,如key0, key1等 for key in [k for k in item if k.startswith('key')]: if key in item and item[key]: # 对应的value键应该是value0, value1等 value_key = 'value' + key[3:] if value_key in item and item[value_key]: headers[item[key]] = item[value_key] # 如果是字典格式,直接使用 elif isinstance(header_data, dict): headers = header_data except json.JSONDecodeError: logger.warning(f"无法解析headers JSON: {header_param}") elif isinstance(header_param, dict): headers = header_param media_type = input_params.get("mediaType", "JSON") retry = input_params.get("retry", False) # 确保retry_times为整数 retry_times = input_params.get("retryTimes", 3) if isinstance(retry_times, str): try: retry_times = int(retry_times) except ValueError: retry_times = 3 # 确保retry_interval为整数 retry_interval = input_params.get("retryInterval", 1000) if isinstance(retry_interval, str): try: retry_interval = int(retry_interval) except ValueError: retry_interval = 1000 if not url: result = { "success": False, "message": "缺少请求URL" } # 记录执行结果 await self._record_task_log(block, result, context) return result # 准备请求数据 try: if isinstance(params, str): data = json.loads(params) else: data = params except: data = params # 如果无法解析为JSON,使用原始字符串 # 设置Content-Type content_type = "application/json" if media_type == "HTML": content_type = "text/html" elif media_type == "XML": content_type = "application/xml" elif media_type == "XWWWFORMURLENCODED": content_type = "application/x-www-form-urlencoded" elif media_type == "JAVASCRIPT": content_type = "application/javascript" if "Content-Type" not in headers: headers["Content-Type"] = content_type # 执行HTTP请求 attempt = 0 max_attempts = 1 if not retry else retry_times + 1 while attempt < max_attempts: try: async with aiohttp.ClientSession() as session: async with session.post(url, json=data, headers=headers) as response: # 读取响应内容 response_text = await response.text() # 尝试解析JSON try: response_json = await response.json() context.set_variable("response", response_json) except: # 不是有效的JSON,保存为文本 context.set_variable("response", response_text) result = { "success": True, "message": f"HTTP POST请求成功,状态码: {response.status}, 响应内容详情: {response_text}", } # 记录执行结果 await self._record_task_log(block, result, context) return result except Exception as e: attempt += 1 if attempt >= max_attempts: raise # 重试间隔 await asyncio.sleep(retry_interval / 1000) except Exception as e: result = { "success": False, "message": f"HTTP POST请求失败: {str(e)}" } # 记录异常 await self._record_task_log(block, result, context) return result