270 lines
10 KiB
Python
270 lines
10 KiB
Python
|
"""
|
|||
|
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
|
|||
|
|