diff --git a/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs b/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs index b4bf84b03..ca41e3fd8 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/game_distribution_publish.rs @@ -5,8 +5,9 @@ //! 其它素材上传链路。 use crate::game_package_upload::{ - game_package_upload_staging_dir, stage_game_package_bytes, upload_staged_game_package, - GamePackageUploadOutcome, GamePackageUploadRequest, StagedGamePackage, + game_package_upload_staging_dir, server_error_detail, stage_game_package_bytes, + upload_staged_game_package, GamePackageUploadOutcome, GamePackageUploadRequest, + StagedGamePackage, }; use crate::http_client::agc_main_site_client_builder; use crate::platform_session::{ @@ -194,10 +195,9 @@ fn response_data(body: &str) -> Result { serde_json::from_str(body).map_err(|error| format!("服务端响应不是合法 JSON:{error}"))?; if value.get("ok").and_then(Value::as_bool) == Some(false) { let (code, message) = parse_error_payload(body); - return Err(message - .filter(|detail| !detail.trim().is_empty()) - .or_else(|| code.filter(|detail| !detail.trim().is_empty())) - .unwrap_or_else(|| "服务器未返回错误信息".to_string())); + return Err(server_error_detail(code, message, || { + "服务器未返回错误信息".to_string() + })); } Ok(value.get("data").cloned().unwrap_or(value)) } @@ -211,13 +211,10 @@ fn map_http_error(status: StatusCode, body: &str, fallback: &str) -> String { if status == StatusCode::FORBIDDEN { return format!( "permission-denied: {}", - message.unwrap_or_else(|| "当前账号无权执行此操作".to_string()) + server_error_detail(code, message, || "当前账号无权执行此操作".to_string()) ); } - let detail = message - .filter(|value| !value.trim().is_empty()) - .or_else(|| code.filter(|value| !value.trim().is_empty())) - .unwrap_or_else(|| format!("HTTP {}", status.as_u16())); + let detail = server_error_detail(code, message, || format!("HTTP {}", status.as_u16())); format!("{fallback}:{detail}") } diff --git a/apps/ai-game-creator-shell/src-tauri/src/game_package_upload.rs b/apps/ai-game-creator-shell/src-tauri/src/game_package_upload.rs index 42ede48ea..d90d18c3d 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/game_package_upload.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/game_package_upload.rs @@ -134,6 +134,19 @@ fn parse_server_error(status: u16, body: &str) -> (Option, Option, + message: Option, + fallback: impl FnOnce() -> String, +) -> String { + message + .filter(|detail| !detail.trim().is_empty()) + .or_else(|| code.filter(|detail| !detail.trim().is_empty())) + .unwrap_or_else(fallback) +} + /// 从 409 响应里取权威已收字节;取不到就返回 `None`,由调用方按失败处理。 fn parse_received_bytes(body: &str) -> Option { let parsed = serde_json::from_str::(body).ok()?; diff --git a/apps/ai-game-creator-shell/src-tauri/src/game_package_upload/runtime.rs b/apps/ai-game-creator-shell/src-tauri/src/game_package_upload/runtime.rs index b06eb543a..9fc2f6ce9 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/game_package_upload/runtime.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/game_package_upload/runtime.rs @@ -155,10 +155,7 @@ async fn read_upload_state( })?; if status >= 400 { let (code, message) = parse_server_error(status, &body); - let detail = message - .filter(|detail| !detail.trim().is_empty()) - .or_else(|| code.filter(|detail| !detail.trim().is_empty())) - .unwrap_or_else(|| format!("HTTP {status}")); + let detail = server_error_detail(code, message, || format!("HTTP {status}")); return Err(GamePackageUploadError::read_upload_state(detail)); } let parsed: Value = serde_json::from_str(&body).map_err(|error| { @@ -213,30 +210,21 @@ async fn upload_chunk( })?; return Ok(received); } - let detail = message - .filter(|detail| !detail.trim().is_empty()) - .or_else(|| code.filter(|detail| !detail.trim().is_empty())) - .unwrap_or_else(|| format!("HTTP {status}")); + let detail = server_error_detail(code, message, || format!("HTTP {status}")); return Err(ChunkUploadError::Fatal( GamePackageUploadError::upload_chunk(detail), )); } if status >= 500 || status == 408 || status == 429 { let (code, message) = parse_server_error(status, &text); - let detail = message - .filter(|detail| !detail.trim().is_empty()) - .or_else(|| code.filter(|detail| !detail.trim().is_empty())) - .unwrap_or_else(|| format!("HTTP {status}")); + let detail = server_error_detail(code, message, || format!("HTTP {status}")); return Err(ChunkUploadError::Retryable( GamePackageUploadError::upload_chunk(detail), )); } if status >= 400 { let (code, message) = parse_server_error(status, &text); - let detail = message - .filter(|detail| !detail.trim().is_empty()) - .or_else(|| code.filter(|detail| !detail.trim().is_empty())) - .unwrap_or_else(|| format!("HTTP {status}")); + let detail = server_error_detail(code, message, || format!("HTTP {status}")); return Err(ChunkUploadError::Fatal( GamePackageUploadError::upload_chunk(detail), )); @@ -285,10 +273,7 @@ async fn complete_upload( })?; if status >= 400 { let (code, message) = parse_server_error(status, &text); - let detail = message - .filter(|detail| !detail.trim().is_empty()) - .or_else(|| code.filter(|detail| !detail.trim().is_empty())) - .unwrap_or_else(|| format!("HTTP {status}")); + let detail = server_error_detail(code, message, || format!("HTTP {status}")); return Err(GamePackageUploadError::complete_upload(detail)); } let parsed: Value = serde_json::from_str(&text).map_err(|error| {