diff --git a/src-tauri/src/database/tests.rs b/src-tauri/src/database/tests.rs index 651ad8f05..f7af3ec91 100644 --- a/src-tauri/src/database/tests.rs +++ b/src-tauri/src/database/tests.rs @@ -245,7 +245,7 @@ fn dry_run_validates_schema_compatibility() { meta: None, icon: None, icon_color: None, - is_proxy_target: false, + is_proxy_target: Some(false), }, ); diff --git a/src-tauri/src/proxy/forwarder.rs b/src-tauri/src/proxy/forwarder.rs index 8b3fb387f..29c28189e 100644 --- a/src-tauri/src/proxy/forwarder.rs +++ b/src-tauri/src/proxy/forwarder.rs @@ -179,12 +179,8 @@ impl RequestForwarder { // 提取 base_url let base_url = self.extract_base_url(provider)?; - // 智能拼接 URL,避免重复的 /v1 - let url = if base_url.ends_with("/v1") && endpoint.starts_with("/v1") { - format!("{}{}", base_url.trim_end_matches("/v1"), endpoint) - } else { - format!("{base_url}{endpoint}") - }; + // 使用辅助函数构建完整 URL(自动去重版本路径) + let url = self.build_full_url(&base_url, endpoint); // 构建请求 let mut request = self.client.post(&url); @@ -277,6 +273,28 @@ impl RequestForwarder { Ok(request) } + /// 构建完整 URL(智能去重版本路径) + fn build_full_url(&self, base_url: &str, endpoint: &str) -> String { + let base_trimmed = base_url.trim_end_matches('/'); + let endpoint_trimmed = endpoint.trim_start_matches('/'); + + // 检查是否存在版本路径重复 + let version_patterns = ["/v1beta", "/v1"]; + let mut final_url = format!("{base_trimmed}/{endpoint_trimmed}"); + + for pattern in &version_patterns { + let duplicate_pattern = format!("{pattern}{pattern}"); + if final_url.contains(&duplicate_pattern) { + final_url = final_url.replace(&duplicate_pattern, pattern); + log::debug!( + "URL 去重: 移除重复的 {pattern} (base: {base_url}, endpoint: {endpoint})" + ); + } + } + + final_url + } + /// 从 Provider 配置中提取 base_url fn extract_base_url(&self, provider: &Provider) -> Result { log::debug!("Extracting base_url for provider: {}", provider.name); @@ -370,8 +388,12 @@ impl RequestForwarder { return Some((key.to_string(), AuthType::Anthropic)); } - // Gemini - if let Some(key) = env.get("GEMINI_API_KEY").and_then(|v| v.as_str()) { + // Gemini (支持两种字段名,优先使用标准的 GOOGLE_GEMINI_API_KEY) + if let Some(key) = env + .get("GOOGLE_GEMINI_API_KEY") + .or_else(|| env.get("GEMINI_API_KEY")) + .and_then(|v| v.as_str()) + { return Some((key.to_string(), AuthType::Gemini)); } @@ -540,11 +562,7 @@ impl RequestForwarder { headers: &axum::http::HeaderMap, ) -> Result { let base_url = self.extract_base_url(provider)?; - let url = if base_url.ends_with("/v1") && endpoint.starts_with("/v1") { - format!("{}{}", base_url.trim_end_matches("/v1"), endpoint) - } else { - format!("{base_url}{endpoint}") - }; + let url = self.build_full_url(&base_url, endpoint); log::info!("Proxy GET Request URL: {url}"); @@ -599,11 +617,7 @@ impl RequestForwarder { headers: &axum::http::HeaderMap, ) -> Result { let base_url = self.extract_base_url(provider)?; - let url = if base_url.ends_with("/v1") && endpoint.starts_with("/v1") { - format!("{}{}", base_url.trim_end_matches("/v1"), endpoint) - } else { - format!("{base_url}{endpoint}") - }; + let url = self.build_full_url(&base_url, endpoint); log::info!("Proxy DELETE Request URL: {url}"); diff --git a/src-tauri/src/proxy/handlers.rs b/src-tauri/src/proxy/handlers.rs index b11daa95e..0c06ddcdb 100644 --- a/src-tauri/src/proxy/handlers.rs +++ b/src-tauri/src/proxy/handlers.rs @@ -93,10 +93,10 @@ pub async fn handle_count_tokens( Ok(builder.body(body).unwrap()) } -/// 处理 Gemini API 请求(透传) +/// 处理 Gemini API 请求(透传,包括查询参数) pub async fn handle_gemini( State(state): State, - axum::extract::Path(path): axum::extract::Path, + uri: axum::http::Uri, headers: axum::http::HeaderMap, Json(body): Json, ) -> Result { @@ -108,9 +108,16 @@ pub async fn handle_gemini( state.status.clone(), ); - let endpoint = format!("/{path}"); + // 提取完整的路径和查询参数 + let endpoint = uri + .path_and_query() + .map(|pq| pq.as_str()) + .unwrap_or(uri.path()); + + log::debug!("Gemini request endpoint (with query): {endpoint}"); + let response = forwarder - .forward_with_retry(&AppType::Gemini, &endpoint, body, headers) + .forward_with_retry(&AppType::Gemini, endpoint, body, headers) .await?; // 透传响应 diff --git a/src-tauri/src/proxy/types.rs b/src-tauri/src/proxy/types.rs index 209a999db..722862977 100644 --- a/src-tauri/src/proxy/types.rs +++ b/src-tauri/src/proxy/types.rs @@ -22,7 +22,7 @@ impl Default for ProxyConfig { Self { enabled: false, listen_address: "127.0.0.1".to_string(), - listen_port: 5000, + listen_port: 15721, // 使用较少占用的高位端口 max_retries: 3, request_timeout: 300, enable_logging: true,