255 lines
9.4 KiB
Python
255 lines
9.4 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
动态API路由处理器
|
||
处理脚本注册的动态API请求
|
||
"""
|
||
|
||
import time
|
||
import asyncio
|
||
from fastapi import APIRouter, Request
|
||
from services.online_script.script_registry_service import get_global_registry
|
||
from utils.logger import get_logger
|
||
from utils.api_response import success_response, error_response
|
||
|
||
logger = get_logger("routes.dynamic_api")
|
||
router = APIRouter()
|
||
|
||
|
||
@router.api_route("/api/dynamic/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
|
||
async def handle_dynamic_api(request: Request, path: str):
|
||
"""处理脚本注册的动态API请求"""
|
||
try:
|
||
registry = get_global_registry()
|
||
method = request.method
|
||
route_key = f"{method}:/{path}"
|
||
|
||
# 查找对应的路由处理器
|
||
route_info = registry.get_api_route(f"/{path}", method)
|
||
if not route_info:
|
||
return error_response(f"API路由未找到: {method} /{path}", code=404)
|
||
|
||
# 获取请求数据
|
||
request_data = {
|
||
"method": method,
|
||
"path": f"/{path}",
|
||
"query_params": dict(request.query_params),
|
||
"headers": dict(request.headers)
|
||
}
|
||
|
||
# 处理请求体数据
|
||
if method in ["POST", "PUT", "PATCH"]:
|
||
try:
|
||
body = await request.json()
|
||
request_data["body"] = body
|
||
except:
|
||
request_data["body"] = {}
|
||
else:
|
||
request_data["body"] = {}
|
||
|
||
# 获取处理器
|
||
handler = route_info["handler"]
|
||
start_time = time.time()
|
||
|
||
# 处理简化参数格式
|
||
params = route_info.get("params", {})
|
||
if params and method in ["POST", "PUT", "PATCH"]:
|
||
# 从请求体提取参数并传递给处理器(新的简化格式)
|
||
handler_args = {}
|
||
for param_name, default_value in params.items():
|
||
handler_args[param_name] = request_data["body"].get(param_name, default_value)
|
||
|
||
# 检测处理器是否为异步函数
|
||
if asyncio.iscoroutinefunction(handler):
|
||
result = await handler(**handler_args)
|
||
else:
|
||
result = handler(**handler_args)
|
||
else:
|
||
# 传递原始请求数据(兼容旧格式)
|
||
if asyncio.iscoroutinefunction(handler):
|
||
result = await handler(request_data)
|
||
else:
|
||
result = handler(request_data)
|
||
|
||
# 计算响应时间
|
||
response_time_ms = int((time.time() - start_time) * 1000)
|
||
|
||
# 更新调用统计
|
||
registry.update_api_call_stats(route_key, response_time_ms)
|
||
|
||
logger.info(f"动态API调用成功: {method} /{path} (脚本: {route_info['script_id']}, 耗时: {response_time_ms}ms)")
|
||
|
||
return success_response(
|
||
data=result,
|
||
message=f"API调用成功"
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"动态API处理失败: {method} /{path} - {e}", exc_info=True)
|
||
return error_response(f"动态API处理失败: {str(e)}", code=500)
|
||
|
||
|
||
@router.get("/api/dynamic-registry/status")
|
||
async def get_dynamic_registry_status():
|
||
"""获取动态API注册状态"""
|
||
try:
|
||
registry = get_global_registry()
|
||
registrations = registry.get_all_registrations()
|
||
|
||
# 统计信息
|
||
stats = {
|
||
"total_apis": len(registrations["api_routes"]),
|
||
"total_functions": len(registrations["registered_functions"]),
|
||
"total_events": sum(len(listeners) for listeners in registrations["event_listeners"].values()),
|
||
"total_timers": len(registrations["timers"]),
|
||
"active_scripts": len(registrations["active_scripts"])
|
||
}
|
||
|
||
return success_response(
|
||
data={
|
||
"stats": stats,
|
||
"registrations": registrations
|
||
},
|
||
message="获取注册状态成功"
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取动态注册状态失败: {e}", exc_info=True)
|
||
return error_response(f"获取注册状态失败: {str(e)}")
|
||
|
||
|
||
@router.get("/api/dynamic-registry/apis")
|
||
async def list_dynamic_apis():
|
||
"""列出所有动态注册的API"""
|
||
try:
|
||
registry = get_global_registry()
|
||
api_routes = registry.api_routes
|
||
|
||
# 格式化API列表
|
||
api_list = []
|
||
for route_key, route_info in api_routes.items():
|
||
api_list.append({
|
||
"route_key": route_key,
|
||
"path": route_info["path"],
|
||
"method": route_info["method"],
|
||
"script_id": route_info["script_id"],
|
||
"description": route_info["description"],
|
||
"call_count": route_info["call_count"],
|
||
"last_called_at": route_info["last_called_at"],
|
||
"average_response_time_ms": route_info["average_response_time_ms"],
|
||
"registered_at": route_info["registered_at"],
|
||
"params": route_info.get("params", {}) # 显示简化的参数格式
|
||
})
|
||
|
||
return success_response(
|
||
data={"apis": api_list, "total": len(api_list)},
|
||
message=f"获取动态API列表成功,共{len(api_list)}个接口"
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取动态API列表失败: {e}", exc_info=True)
|
||
return error_response(f"获取API列表失败: {str(e)}")
|
||
|
||
|
||
@router.get("/api/dynamic-registry/functions")
|
||
async def list_dynamic_functions():
|
||
"""列出所有动态注册的函数"""
|
||
try:
|
||
registry = get_global_registry()
|
||
functions = registry.registered_functions
|
||
|
||
# 格式化函数列表
|
||
function_list = []
|
||
for function_name, function_info in functions.items():
|
||
function_list.append({
|
||
"name": function_name,
|
||
"script_id": function_info["script_id"],
|
||
"description": function_info["description"],
|
||
"is_async": function_info["is_async"],
|
||
"call_count": function_info["call_count"],
|
||
"success_count": function_info["success_count"],
|
||
"error_count": function_info["error_count"],
|
||
"last_called_at": function_info["last_called_at"],
|
||
"average_execution_time_ms": function_info["average_execution_time_ms"],
|
||
"registered_at": function_info["registered_at"],
|
||
"params": function_info.get("params", {}), # 显示简化的参数格式
|
||
"tags": function_info["tags"]
|
||
})
|
||
|
||
return success_response(
|
||
data={"functions": function_list, "total": len(function_list)},
|
||
message=f"获取动态函数列表成功,共{len(function_list)}个函数"
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取动态函数列表失败: {e}", exc_info=True)
|
||
return error_response(f"获取函数列表失败: {str(e)}")
|
||
|
||
|
||
@router.post("/api/dynamic-registry/test-function/{function_name}")
|
||
async def test_dynamic_function(function_name: str, request: Request):
|
||
"""测试动态注册的函数"""
|
||
try:
|
||
registry = get_global_registry()
|
||
function_info = registry.get_function_info(function_name)
|
||
|
||
if not function_info:
|
||
return error_response(f"函数 {function_name} 未注册")
|
||
|
||
# 获取测试参数
|
||
try:
|
||
test_args = await request.json()
|
||
except:
|
||
test_args = {}
|
||
|
||
# 获取处理器
|
||
handler = function_info["handler"]
|
||
start_time = time.time()
|
||
|
||
# 处理简化参数格式
|
||
params = function_info.get("params", {})
|
||
if params:
|
||
# 使用简化的参数格式
|
||
handler_args = {}
|
||
for param_name, default_value in params.items():
|
||
handler_args[param_name] = test_args.get(param_name, default_value)
|
||
|
||
if function_info["is_async"]:
|
||
result = await handler(**handler_args)
|
||
else:
|
||
result = handler(**handler_args)
|
||
else:
|
||
# 兼容旧格式
|
||
if function_info["is_async"]:
|
||
result = await handler(test_args)
|
||
else:
|
||
result = handler(test_args)
|
||
|
||
# 计算执行时间
|
||
execution_time_ms = int((time.time() - start_time) * 1000)
|
||
|
||
# 更新统计
|
||
registry.update_function_call_stats(function_name, execution_time_ms, True)
|
||
|
||
logger.info(f"动态函数测试成功: {function_name} (脚本: {function_info['script_id']}, 耗时: {execution_time_ms}ms)")
|
||
|
||
return success_response(
|
||
data={
|
||
"result": result,
|
||
"execution_time_ms": execution_time_ms,
|
||
"function_name": function_name,
|
||
"script_id": function_info["script_id"]
|
||
},
|
||
message=f"函数测试成功"
|
||
)
|
||
|
||
except Exception as e:
|
||
logger.error(f"测试动态函数失败: {function_name} - {e}", exc_info=True)
|
||
|
||
# 更新失败统计
|
||
if function_info:
|
||
execution_time_ms = int((time.time() - start_time) * 1000) if 'start_time' in locals() else 0
|
||
registry.update_function_call_stats(function_name, execution_time_ms, False)
|
||
|
||
return error_response(f"函数测试失败: {str(e)}") |