pub trait HttpClient: Send + Sync {
// Required methods
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_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;
// Provided methods
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 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 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 { ... }
}
Expand description
HTTP transport client abstraction, defining common HTTP operation interface
HTTP transport client abstraction defining generic HTTP operation interface
This trait defines the generic interface for all HTTP operations, allowing the adapter layer to avoid direct interaction with reqwest
Required Methodsยง
Sourcefn 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
Sourcefn 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
Provided Methodsยง
Sourcefn 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
Examples found in repository?
examples/debug_openai_transport.rs (line 28)
7async fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("๐ OpenAI Transport Layer Debugging");
9 println!("==================================");
10
11 let api_key = match std::env::var("OPENAI_API_KEY") {
12 Ok(key) => key,
13 Err(_) => {
14 println!("โ OPENAI_API_KEY not set");
15 return Ok(());
16 }
17 };
18
19 // Use our HttpTransport
20 let transport = HttpTransport::new();
21
22 // Test GET request (model list) - we know this works
23 println!("\n๐ Test GET request (model list):");
24 let mut headers = HashMap::new();
25 headers.insert("Authorization".to_string(), format!("Bearer {}", api_key));
26
27 match transport
28 .get::<serde_json::Value>("https://api.openai.com/v1/models", Some(headers))
29 .await
30 {
31 Ok(response) => {
32 let model_count = response["data"]
33 .as_array()
34 .map(|arr| arr.len())
35 .unwrap_or(0);
36 println!("โ
GET request successful, got {} models", model_count);
37 }
38 Err(e) => {
39 println!("โ GET request failed: {}", e);
40 }
41 }
42
43 // Test POST request (chat completion) - this has issues
44 println!("\n๐ฌ Test POST request (chat completion):");
45 let mut headers = HashMap::new();
46 headers.insert("Authorization".to_string(), format!("Bearer {}", api_key));
47
48 let request_body = json!({
49 "model": "gpt-3.5-turbo",
50 "messages": [
51 {
52 "role": "user",
53 "content": "Say 'test' in one word."
54 }
55 ],
56 "max_tokens": 5
57 });
58
59 println!(
60 "Request body: {}",
61 serde_json::to_string_pretty(&request_body)?
62 );
63
64 match transport
65 .post::<serde_json::Value, serde_json::Value>(
66 "https://api.openai.com/v1/chat/completions",
67 Some(headers),
68 &request_body,
69 )
70 .await
71 {
72 Ok(response) => {
73 println!("โ
POST request successful!");
74 println!("Response: {}", serde_json::to_string_pretty(&response)?);
75 }
76 Err(e) => {
77 println!("โ POST request failed: {}", e);
78
79 // Analyze error type
80 let error_str = e.to_string();
81 if error_str.contains("you must provide a model parameter") {
82 println!("๐ This error is strange because we did provide the model parameter");
83 println!(" Possible reasons:");
84 println!(" 1. Proxy server modified the request body");
85 println!(" 2. Content-Type header issue");
86 println!(" 3. JSON serialization issue");
87 }
88 }
89 }
90
91 println!("\n๐ก Debug Conclusion:");
92 println!(" โข GET request works โ authentication and network connection OK");
93 println!(" โข POST request fails โ may be proxy or request format issue");
94 println!(" โข Recommend checking proxy server's POST request handling");
95
96 Ok(())
97}
Sourcefn 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
Examples found in repository?
examples/debug_openai_transport.rs (lines 65-69)
7async fn main() -> Result<(), Box<dyn std::error::Error>> {
8 println!("๐ OpenAI Transport Layer Debugging");
9 println!("==================================");
10
11 let api_key = match std::env::var("OPENAI_API_KEY") {
12 Ok(key) => key,
13 Err(_) => {
14 println!("โ OPENAI_API_KEY not set");
15 return Ok(());
16 }
17 };
18
19 // Use our HttpTransport
20 let transport = HttpTransport::new();
21
22 // Test GET request (model list) - we know this works
23 println!("\n๐ Test GET request (model list):");
24 let mut headers = HashMap::new();
25 headers.insert("Authorization".to_string(), format!("Bearer {}", api_key));
26
27 match transport
28 .get::<serde_json::Value>("https://api.openai.com/v1/models", Some(headers))
29 .await
30 {
31 Ok(response) => {
32 let model_count = response["data"]
33 .as_array()
34 .map(|arr| arr.len())
35 .unwrap_or(0);
36 println!("โ
GET request successful, got {} models", model_count);
37 }
38 Err(e) => {
39 println!("โ GET request failed: {}", e);
40 }
41 }
42
43 // Test POST request (chat completion) - this has issues
44 println!("\n๐ฌ Test POST request (chat completion):");
45 let mut headers = HashMap::new();
46 headers.insert("Authorization".to_string(), format!("Bearer {}", api_key));
47
48 let request_body = json!({
49 "model": "gpt-3.5-turbo",
50 "messages": [
51 {
52 "role": "user",
53 "content": "Say 'test' in one word."
54 }
55 ],
56 "max_tokens": 5
57 });
58
59 println!(
60 "Request body: {}",
61 serde_json::to_string_pretty(&request_body)?
62 );
63
64 match transport
65 .post::<serde_json::Value, serde_json::Value>(
66 "https://api.openai.com/v1/chat/completions",
67 Some(headers),
68 &request_body,
69 )
70 .await
71 {
72 Ok(response) => {
73 println!("โ
POST request successful!");
74 println!("Response: {}", serde_json::to_string_pretty(&response)?);
75 }
76 Err(e) => {
77 println!("โ POST request failed: {}", e);
78
79 // Analyze error type
80 let error_str = e.to_string();
81 if error_str.contains("you must provide a model parameter") {
82 println!("๐ This error is strange because we did provide the model parameter");
83 println!(" Possible reasons:");
84 println!(" 1. Proxy server modified the request body");
85 println!(" 2. Content-Type header issue");
86 println!(" 3. JSON serialization issue");
87 }
88 }
89 }
90
91 println!("\n๐ก Debug Conclusion:");
92 println!(" โข GET request works โ authentication and network connection OK");
93 println!(" โข POST request fails โ may be proxy or request format issue");
94 println!(" โข Recommend checking proxy server's POST request handling");
95
96 Ok(())
97}
Sourcefn 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
Dyn Compatibilityยง
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.