refactor: improve profile creation api invalid 'browser' handling

This commit is contained in:
zhom
2026-06-24 08:01:46 +04:00
parent 931d02fefd
commit 19e50324c4
+36 -7
View File
@@ -57,6 +57,9 @@ pub struct ApiProfileResponse {
#[derive(Debug, Serialize, Deserialize, ToSchema)] #[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct CreateProfileRequest { pub struct CreateProfileRequest {
pub name: String, pub name: String,
/// Browser engine. Must be `"wayfern"` (anti-detect Chromium) or `"camoufox"`
/// (anti-detect Firefox). Any other value (e.g. `"chromium"`) is rejected with
/// 400.
pub browser: String, pub browser: String,
/// Optional. Omit (or pass `"latest"`) to use the newest already-downloaded /// Optional. Omit (or pass `"latest"`) to use the newest already-downloaded
/// version of the chosen browser. A concrete version must already be /// version of the chosen browser. A concrete version must already be
@@ -815,7 +818,7 @@ async fn get_profile(
async fn create_profile( async fn create_profile(
State(state): State<ApiServerState>, State(state): State<ApiServerState>,
Json(request): Json<CreateProfileRequest>, Json(request): Json<CreateProfileRequest>,
) -> Result<Json<ApiProfileResponse>, StatusCode> { ) -> Result<Json<ApiProfileResponse>, (StatusCode, String)> {
let profile_manager = ProfileManager::instance(); let profile_manager = ProfileManager::instance();
// Only Wayfern and Camoufox profiles are launchable; the rest of the system // Only Wayfern and Camoufox profiles are launchable; the rest of the system
@@ -824,7 +827,13 @@ async fn create_profile(
// unrecognized browser, then crashes with a 500 on /run. Mirrors the MCP // unrecognized browser, then crashes with a 500 on /run. Mirrors the MCP
// create_profile validation. // create_profile validation.
if request.browser != "wayfern" && request.browser != "camoufox" { if request.browser != "wayfern" && request.browser != "camoufox" {
return Err(StatusCode::BAD_REQUEST); return Err((
StatusCode::BAD_REQUEST,
format!(
"Invalid browser \"{}\". Must be \"wayfern\" (anti-detect Chromium) or \"camoufox\" (anti-detect Firefox).",
request.browser
),
));
} }
// Resolve the version. Omitted, empty, or "latest" means "newest version // Resolve the version. Omitted, empty, or "latest" means "newest version
@@ -841,7 +850,15 @@ async fn create_profile(
versions.sort_by(|a, b| crate::api_client::compare_versions(b, a)); versions.sort_by(|a, b| crate::api_client::compare_versions(b, a));
match versions.into_iter().next() { match versions.into_iter().next() {
Some(v) => v, Some(v) => v,
None => return Err(StatusCode::BAD_REQUEST), None => {
return Err((
StatusCode::BAD_REQUEST,
format!(
"No downloaded version of \"{}\" is available. Download the browser in Donut Browser first — this endpoint does not download browsers.",
request.browser
),
));
}
} }
} }
}; };
@@ -866,9 +883,15 @@ async fn create_profile(
crate::validate_profile_network(request.proxy_id.as_deref(), request.vpn_id.as_deref()).await crate::validate_profile_network(request.proxy_id.as_deref(), request.vpn_id.as_deref()).await
{ {
return Err(if err.contains("PROXY_PAYMENT_REQUIRED") { return Err(if err.contains("PROXY_PAYMENT_REQUIRED") {
StatusCode::PAYMENT_REQUIRED (
StatusCode::PAYMENT_REQUIRED,
"The selected proxy requires an active subscription.".to_string(),
)
} else { } else {
StatusCode::BAD_REQUEST (
StatusCode::BAD_REQUEST,
format!("Profile network validation failed: {err}"),
)
}); });
} }
@@ -898,7 +921,10 @@ async fn create_profile(
.update_profile_tags(&state.app_handle, &profile.name, tags.clone()) .update_profile_tags(&state.app_handle, &profile.name, tags.clone())
.is_err() .is_err()
{ {
return Err(StatusCode::INTERNAL_SERVER_ERROR); return Err((
StatusCode::INTERNAL_SERVER_ERROR,
"Profile created but failed to apply tags.".to_string(),
));
} }
profile.tags = tags.clone(); profile.tags = tags.clone();
} }
@@ -930,7 +956,10 @@ async fn create_profile(
}, },
})) }))
} }
Err(_) => Err(StatusCode::BAD_REQUEST), Err(e) => Err((
StatusCode::BAD_REQUEST,
format!("Failed to create profile: {e}"),
)),
} }
} }