""" POST /proxy — RTC OpenAPI 代理(含请求签名) """ import httpx from fastapi import APIRouter, Request from fastapi.responses import JSONResponse from config.custom_scene import get_rtc_openapi_version from security.signer import Signer from services.scene_service import Scenes, prepare_scene_runtime from services.session_store import load_session from utils.responses import error_response from utils.validation import assert_scene_value, assert_value router = APIRouter() @router.post("/proxy") async def proxy(request: Request): action = request.query_params.get("Action", "") version = request.query_params.get("Version") or get_rtc_openapi_version() try: assert_value(action, "Action 不能为空") assert_value(version, "Version 不能为空") body = await request.json() scene_id = body.get("SceneID", "") assert_value(scene_id, "SceneID 不能为空,SceneID 用于指定场景配置") json_data = Scenes.get(scene_id) if not json_data: raise ValueError(f"{scene_id} 不存在,请先配置对应场景。") _, _, voice_chat = prepare_scene_runtime(scene_id, json_data) account_config = json_data.get("AccountConfig", {}) assert_scene_value( scene_id, "AccountConfig.accessKeyId", account_config.get("accessKeyId") ) assert_scene_value( scene_id, "AccountConfig.secretKey", account_config.get("secretKey") ) if action == "StartVoiceChat": # 从 session 取回 getScenes 时分配的 RoomId/UserId/TaskId sess = load_session(request, scene_id) if sess.get("RoomId"): voice_chat["RoomId"] = sess["RoomId"] if sess.get("TaskId"): voice_chat["TaskId"] = sess["TaskId"] if sess.get("UserId"): agent_config = voice_chat.get("AgentConfig", {}) target_user_ids = agent_config.get("TargetUserId", []) if target_user_ids: target_user_ids[0] = sess["UserId"] else: agent_config["TargetUserId"] = [sess["UserId"]] req_body = voice_chat elif action == "StopVoiceChat": app_id = voice_chat.get("AppId", "") sess = load_session(request, scene_id) room_id = sess.get("RoomId") or voice_chat.get("RoomId", "") task_id = sess.get("TaskId") or voice_chat.get("TaskId", "") assert_scene_value(scene_id, "VoiceChat.AppId", app_id) assert_scene_value(scene_id, "VoiceChat.RoomId", room_id) assert_scene_value(scene_id, "VoiceChat.TaskId", task_id) req_body = {"AppId": app_id, "RoomId": room_id, "TaskId": task_id} else: req_body = {} request_data = { "region": "cn-north-1", "method": "POST", "params": {"Action": action, "Version": version}, "headers": { "Host": "rtc.volcengineapi.com", "Content-type": "application/json", }, "body": req_body, } signer = Signer(request_data, "rtc") signer.add_authorization(account_config) async with httpx.AsyncClient() as client: resp = await client.post( f"https://rtc.volcengineapi.com?Action={action}&Version={version}", headers=request_data["headers"], json=req_body, ) return JSONResponse(resp.json()) except ValueError as e: return error_response(action, str(e)) except Exception as e: return error_response(action, str(e))