pub struct HttpTransport { /* private fields */ }
Expand description
基于reqwest的HTTP传输实现,封装所有HTTP细节
HTTP transport implementation based on reqwest, encapsulating all HTTP details
This is the concrete implementation of the HttpClient trait, encapsulating all HTTP details
Implementations§
Source§impl HttpTransport
impl HttpTransport
Sourcepub fn new() -> Self
pub fn new() -> Self
Create new HTTP transport instance
Automatically detects AI_PROXY_URL environment variable for proxy configuration
Examples found in repository?
examples/debug_openai_transport.rs (line 19)
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 println!("🔍 OpenAI传输层调试");
8 println!("===================");
9
10 let api_key = match std::env::var("OPENAI_API_KEY") {
11 Ok(key) => key,
12 Err(_) => {
13 println!("❌ 未设置OPENAI_API_KEY");
14 return Ok(());
15 }
16 };
17
18 // 使用我们的HttpTransport
19 let transport = HttpTransport::new();
20
21 // 测试GET请求 (模型列表) - 我们知道这个工作
22 println!("\n📋 测试GET请求 (模型列表):");
23 let mut headers = HashMap::new();
24 headers.insert("Authorization".to_string(), format!("Bearer {}", api_key));
25
26 match transport.get::<serde_json::Value>("https://api.openai.com/v1/models", Some(headers)).await {
27 Ok(response) => {
28 let model_count = response["data"].as_array().map(|arr| arr.len()).unwrap_or(0);
29 println!("✅ GET请求成功,获取到 {} 个模型", model_count);
30 }
31 Err(e) => {
32 println!("❌ GET请求失败: {}", e);
33 }
34 }
35
36 // 测试POST请求 (聊天完成) - 这个有问题
37 println!("\n💬 测试POST请求 (聊天完成):");
38 let mut headers = HashMap::new();
39 headers.insert("Authorization".to_string(), format!("Bearer {}", api_key));
40
41 let request_body = json!({
42 "model": "gpt-3.5-turbo",
43 "messages": [
44 {
45 "role": "user",
46 "content": "Say 'test' in one word."
47 }
48 ],
49 "max_tokens": 5
50 });
51
52 println!("请求体: {}", serde_json::to_string_pretty(&request_body)?);
53
54 match transport.post::<serde_json::Value, serde_json::Value>(
55 "https://api.openai.com/v1/chat/completions",
56 Some(headers),
57 &request_body
58 ).await {
59 Ok(response) => {
60 println!("✅ POST请求成功!");
61 println!("响应: {}", serde_json::to_string_pretty(&response)?);
62 }
63 Err(e) => {
64 println!("❌ POST请求失败: {}", e);
65
66 // 分析错误类型
67 let error_str = e.to_string();
68 if error_str.contains("you must provide a model parameter") {
69 println!("🔍 这个错误很奇怪,因为我们确实提供了model参数");
70 println!(" 可能的原因:");
71 println!(" 1. 代理服务器修改了请求体");
72 println!(" 2. Content-Type头部问题");
73 println!(" 3. JSON序列化问题");
74 }
75 }
76 }
77
78 println!("\n💡 调试结论:");
79 println!(" • GET请求工作正常 → 认证和网络连接OK");
80 println!(" • POST请求失败 → 可能是代理或请求格式问题");
81 println!(" • 建议检查代理服务器的POST请求处理");
82
83 Ok(())
84}
Sourcepub fn with_timeout(timeout: Duration) -> Self
pub fn with_timeout(timeout: Duration) -> Self
Create HTTP transport instance with timeout
Automatically detects AI_PROXY_URL environment variable for proxy configuration
Sourcepub fn with_proxy(
timeout: Duration,
proxy_url: Option<&str>,
) -> Result<Self, TransportError>
pub fn with_proxy( timeout: Duration, proxy_url: Option<&str>, ) -> Result<Self, TransportError>
Create HTTP transport instance with custom proxy
Source§impl HttpTransport
impl HttpTransport
Sourcepub fn boxed(self) -> DynHttpTransportRef
pub fn boxed(self) -> DynHttpTransportRef
Produce an Arc-wrapped object-safe transport reference
Trait Implementations§
Source§impl Default for HttpTransport
impl Default for HttpTransport
Source§impl HttpClient for HttpTransport
impl HttpClient for HttpTransport
Source§fn request<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
method: Method,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: Option<&'life2 T>,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn request<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
method: Method,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: Option<&'life2 T>,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Send HTTP request
Source§fn request_with_retry<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
method: Method,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: Option<&'life2 T>,
_max_retries: u32,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + Clone + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn request_with_retry<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
method: Method,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: Option<&'life2 T>,
_max_retries: u32,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + Clone + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Send HTTP request with retry
Source§fn get<'life0, 'life1, 'async_trait, R>(
&'life0 self,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get<'life0, 'life1, 'async_trait, R>(
&'life0 self,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Send GET request
Source§fn post<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: &'life2 T,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn post<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: &'life2 T,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Send POST request
Source§fn put<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: &'life2 T,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn put<'life0, 'life1, 'life2, 'async_trait, T, R>(
&'life0 self,
url: &'life1 str,
headers: Option<HashMap<String, String>>,
body: &'life2 T,
) -> Pin<Box<dyn Future<Output = Result<R, TransportError>> + Send + 'async_trait>>where
T: Serialize + Send + Sync + 'async_trait,
R: for<'de> Deserialize<'de> + 'async_trait,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Send PUT request
Auto Trait Implementations§
impl Freeze for HttpTransport
impl !RefUnwindSafe for HttpTransport
impl Send for HttpTransport
impl Sync for HttpTransport
impl Unpin for HttpTransport
impl !UnwindSafe for HttpTransport
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more