openai_rust_sdk/api/base/
response_handlers.rs1use crate::api::base::client::HttpClient;
4use crate::error::{OpenAIError, Result};
5use serde::de::DeserializeOwned;
6
7impl HttpClient {
8 pub(crate) async fn handle_error_response<T>(
10 &self,
11 response: reqwest::Response,
12 status: reqwest::StatusCode,
13 ) -> Result<T> {
14 let error_text = response
15 .text()
16 .await
17 .unwrap_or_else(|_| "Unknown error".to_string());
18
19 serde_json::from_str::<crate::error::ApiErrorResponse>(&error_text).map_or_else(
21 |_| {
22 Err(OpenAIError::ApiError {
23 status: status.as_u16(),
24 message: error_text,
25 })
26 },
27 |api_error| Err(OpenAIError::from_api_response(status.as_u16(), api_error)),
28 )
29 }
30
31 pub async fn handle_response<T>(&self, response: reqwest::Response) -> Result<T>
33 where
34 T: DeserializeOwned,
35 {
36 let status = response.status();
37
38 if status.is_success() {
39 let text = response.text().await?;
40 serde_json::from_str(&text).map_err(|e| {
41 OpenAIError::ParseError(format!("Failed to parse response: {e}. Response: {text}"))
42 })
43 } else {
44 self.handle_error_response(response, status).await
45 }
46 }
47
48 async fn extract_raw_content<F, R>(
50 &self,
51 response: reqwest::Response,
52 status: reqwest::StatusCode,
53 extractor: F,
54 error_context: &str,
55 ) -> Result<R>
56 where
57 F: FnOnce(
58 reqwest::Response,
59 )
60 -> futures::future::BoxFuture<'static, std::result::Result<R, reqwest::Error>>,
61 R: 'static,
62 {
63 if status.is_success() {
64 extractor(response).await.map_err(crate::map_err!(
65 RequestError,
66 error_context,
67 to_string
68 ))
69 } else {
70 self.handle_error_response(response, status).await
71 }
72 }
73
74 pub async fn get_text(&self, path: &str) -> Result<String> {
76 let url = self.build_simple_url(path);
77 let headers = self.build_headers()?;
78
79 let response = self.client().get(&url).headers(headers).send().await?;
80 let status = response.status();
81
82 self.extract_raw_content(
83 response,
84 status,
85 |r| Box::pin(async move { r.text().await }),
86 "Failed to read response text",
87 )
88 .await
89 }
90
91 pub async fn get_bytes(&self, path: &str) -> Result<Vec<u8>> {
93 let url = self.build_simple_url(path);
94 let headers = self.build_headers()?;
95
96 let response = self.client().get(&url).headers(headers).send().await?;
97 let status = response.status();
98
99 self.extract_raw_content(
100 response,
101 status,
102 |r| Box::pin(async move { r.bytes().await.map(|b| b.to_vec()) }),
103 "Failed to read response bytes",
104 )
105 .await
106 }
107
108 pub async fn post_bytes_with_content_type<B>(
110 &self,
111 path: &str,
112 body: &B,
113 ) -> Result<(Vec<u8>, String)>
114 where
115 B: serde::Serialize,
116 {
117 let url = self.build_simple_url(path);
118 let headers = self.build_headers()?;
119
120 let response = self
121 .client()
122 .post(&url)
123 .headers(headers)
124 .json(body)
125 .send()
126 .await?;
127
128 let status = response.status();
129 if status.is_success() {
130 let content_type = response
131 .headers()
132 .get("content-type")
133 .and_then(|v| v.to_str().ok())
134 .unwrap_or("application/octet-stream")
135 .to_string();
136
137 let bytes = response.bytes().await.map_err(|e| {
138 OpenAIError::RequestError(format!("Failed to read response bytes: {e}"))
139 })?;
140
141 Ok((bytes.to_vec(), content_type))
142 } else {
143 self.handle_error_response(response, status).await
144 }
145 }
146}