feat: add Mihomo API modules and manager (#2869)
• Introduce new API caller implementations for Mihomo in model and module layers. • Add configuration and API integration files under /src-tauri/src/config/api and /src-tauri/src/model/api. • Implement a singleton MihomoAPICaller with async API call support and integration tests. • Create a new MihomoManager module to refresh and fetch proxies from the API. • Update Cargo.lock and Cargo.toml with additional dependencies (async-trait, env_logger, mockito, tempfile, etc.) related to the Mihomo API support.
This commit is contained in:
70
src-tauri/src/module/api/common.rs
Normal file
70
src-tauri/src/module/api/common.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use crate::model::api::common::ApiCaller;
|
||||
use async_trait::async_trait;
|
||||
use reqwest::{
|
||||
header::{HeaderMap, HeaderName, HeaderValue},
|
||||
RequestBuilder,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
impl<'a> ApiCaller<'a> {
|
||||
pub async fn send_request(
|
||||
&self,
|
||||
method: &str,
|
||||
path: &str,
|
||||
body: Option<&str>,
|
||||
headers: Option<Vec<(&str, &str)>>,
|
||||
) -> Result<String, String> {
|
||||
let full_url = format!("{}{}", self.url, path); // 拼接完整 URL
|
||||
let mut request: RequestBuilder = match method {
|
||||
"GET" => self.client.get(&full_url),
|
||||
"POST" => self
|
||||
.client
|
||||
.post(&full_url)
|
||||
.body(body.unwrap_or("").to_string()),
|
||||
"PUT" => self
|
||||
.client
|
||||
.put(&full_url)
|
||||
.body(body.unwrap_or("").to_string()),
|
||||
"DELETE" => self.client.delete(&full_url),
|
||||
_ => return Err("Unsupported HTTP method".to_string()),
|
||||
};
|
||||
|
||||
// 处理 headers
|
||||
if let Some(hdrs) = headers {
|
||||
let mut header_map = HeaderMap::new();
|
||||
for (key, value) in hdrs {
|
||||
if let (Ok(header_name), Ok(header_value)) = (
|
||||
HeaderName::from_bytes(key.as_bytes()),
|
||||
HeaderValue::from_str(value),
|
||||
) {
|
||||
header_map.insert(header_name, header_value);
|
||||
}
|
||||
}
|
||||
request = request.headers(header_map);
|
||||
}
|
||||
|
||||
let response = request.send().await.map_err(|e| e.to_string())?;
|
||||
response.text().await.map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[async_trait]
|
||||
pub trait ApiCallerTrait: Send + Sync {
|
||||
async fn call_api<T>(
|
||||
&self,
|
||||
method: &str,
|
||||
path: &str,
|
||||
body: Option<&str>,
|
||||
headers: Option<Vec<(&str, &str)>>
|
||||
) -> Result<T, String>
|
||||
where
|
||||
T: DeserializeOwned + Send + Sync;
|
||||
|
||||
fn parse_json_response<T>(json_str: &str) -> Result<T, String>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
serde_json::from_str(json_str).map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user