d1a657b5d2
保持401与Bearer挑战并提供机器可读的Key配置步骤 统一缺失格式错误和无效Key响应以避免凭据枚举 保留请求元信息并同步OpenAPI集成清单与架构文档 补充鉴权脱敏契约测试并完成本地dev栈验证
227 lines
8.8 KiB
Rust
227 lines
8.8 KiB
Rust
use axum::{
|
|
Extension, Router,
|
|
extract::DefaultBodyLimit,
|
|
middleware,
|
|
routing::{get, patch, post},
|
|
};
|
|
|
|
use crate::{
|
|
editor_project::EDITOR_LAYOUT_REQUEST_BODY_MAX_BYTES,
|
|
external_api_auth::{require_external_api_key, require_external_mcp_api_key},
|
|
external_assets_api::{
|
|
confirm_external_asset_object, create_external_direct_upload_ticket,
|
|
get_external_asset_read_url,
|
|
},
|
|
external_editor_api::{
|
|
create_external_editor_asset, create_external_editor_asset_folder,
|
|
create_external_editor_project, create_external_editor_project_resource,
|
|
delete_external_editor_asset, delete_external_editor_asset_folder,
|
|
delete_external_editor_project, edit_external_editor_image,
|
|
extract_external_editor_ui_design_assets, generate_external_editor_background_music,
|
|
generate_external_editor_character_animation, generate_external_editor_icon_spritesheet,
|
|
generate_external_editor_image, generate_external_editor_sound_effect,
|
|
generate_external_editor_video, get_external_editor_asset_library,
|
|
get_external_editor_generation_job, get_external_editor_project,
|
|
list_external_editor_projects, load_recent_external_editor_project, openapi_json,
|
|
rename_external_editor_project, save_external_editor_canvas, update_external_editor_asset,
|
|
update_external_editor_asset_folder,
|
|
},
|
|
external_mcp,
|
|
external_skill_api::{
|
|
download_external_skill_archive, get_external_agent_integration_manifest,
|
|
get_external_skill_entry,
|
|
},
|
|
state::AppState,
|
|
};
|
|
|
|
pub fn router(state: AppState) -> Router<AppState> {
|
|
let mcp_router = Router::new()
|
|
.nest_service("/api/external/v1/mcp", external_mcp::service())
|
|
.layer(Extension(state.clone()))
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_mcp_api_key,
|
|
));
|
|
|
|
Router::new()
|
|
.merge(mcp_router)
|
|
.route("/api/external/v1/openapi.json", get(openapi_json))
|
|
.route(
|
|
"/api/external/v1/agent-integration.json",
|
|
get(get_external_agent_integration_manifest),
|
|
)
|
|
.route(
|
|
"/api/external/v1/skill/SKILL.md",
|
|
get(get_external_skill_entry),
|
|
)
|
|
.route(
|
|
"/api/external/v1/skill.zip",
|
|
get(download_external_skill_archive),
|
|
)
|
|
.route(
|
|
"/api/external/v1/assets/direct-upload-tickets",
|
|
post(create_external_direct_upload_ticket).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/assets/objects/confirm",
|
|
post(confirm_external_asset_object).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/assets/read-url",
|
|
get(get_external_asset_read_url).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/projects",
|
|
get(list_external_editor_projects)
|
|
.post(create_external_editor_project)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/projects/recent",
|
|
get(load_recent_external_editor_project).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/projects/{project_id}",
|
|
get(get_external_editor_project)
|
|
.delete(delete_external_editor_project)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/projects/{project_id}/metadata",
|
|
patch(rename_external_editor_project).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/projects/{project_id}/canvas",
|
|
patch(save_external_editor_canvas)
|
|
.layer(DefaultBodyLimit::max(EDITOR_LAYOUT_REQUEST_BODY_MAX_BYTES))
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/projects/{project_id}/resources",
|
|
post(create_external_editor_project_resource).route_layer(
|
|
middleware::from_fn_with_state(state.clone(), require_external_api_key),
|
|
),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/assets/library",
|
|
get(get_external_editor_asset_library).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/assets/folders",
|
|
post(create_external_editor_asset_folder).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/assets/folders/{folder_id}",
|
|
patch(update_external_editor_asset_folder)
|
|
.delete(delete_external_editor_asset_folder)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/assets",
|
|
post(create_external_editor_asset).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/assets/{asset_id}",
|
|
patch(update_external_editor_asset)
|
|
.delete(delete_external_editor_asset)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/generations/{operation_id}",
|
|
get(get_external_editor_generation_job).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/images/generations",
|
|
post(generate_external_editor_image).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/images/edits",
|
|
post(edit_external_editor_image).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/icon-spritesheets/generations",
|
|
post(generate_external_editor_icon_spritesheet).route_layer(
|
|
middleware::from_fn_with_state(state.clone(), require_external_api_key),
|
|
),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/ui-designs/assets/extractions",
|
|
post(extract_external_editor_ui_design_assets).route_layer(
|
|
middleware::from_fn_with_state(state.clone(), require_external_api_key),
|
|
),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/character-animations/generations",
|
|
post(generate_external_editor_character_animation).route_layer(
|
|
middleware::from_fn_with_state(state.clone(), require_external_api_key),
|
|
),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/videos/generations",
|
|
post(generate_external_editor_video).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_external_api_key,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/audios/sound-effects/generations",
|
|
post(generate_external_editor_sound_effect).route_layer(
|
|
middleware::from_fn_with_state(state.clone(), require_external_api_key),
|
|
),
|
|
)
|
|
.route(
|
|
"/api/external/v1/editor/audios/background-music/generations",
|
|
post(generate_external_editor_background_music).route_layer(
|
|
middleware::from_fn_with_state(state, require_external_api_key),
|
|
),
|
|
)
|
|
}
|