100 lines
2.9 KiB
Rust
100 lines
2.9 KiB
Rust
use std::error::Error;
|
||
|
||
use reqwest::header;
|
||
use serde_json::Value;
|
||
|
||
use crate::{error::Hyper3dError, response::parse_api_error_message, types::Hyper3dSettings};
|
||
|
||
pub(crate) async fn post_hyper3d_multipart(
|
||
http_client: &reqwest::Client,
|
||
settings: &Hyper3dSettings,
|
||
path: &str,
|
||
form: reqwest::multipart::Form,
|
||
failure_context: &str,
|
||
) -> Result<Value, Hyper3dError> {
|
||
let response = http_client
|
||
.post(format!("{}{}", settings.base_url, path))
|
||
.header(
|
||
header::AUTHORIZATION,
|
||
format!("Bearer {}", settings.api_key),
|
||
)
|
||
.header(header::ACCEPT, "application/json")
|
||
.multipart(form)
|
||
.send()
|
||
.await
|
||
.map_err(|error| map_reqwest_error(failure_context, path, error))?;
|
||
parse_hyper3d_response(response, failure_context).await
|
||
}
|
||
|
||
pub(crate) async fn post_hyper3d_json(
|
||
http_client: &reqwest::Client,
|
||
settings: &Hyper3dSettings,
|
||
path: &str,
|
||
body: Value,
|
||
failure_context: &str,
|
||
) -> Result<Value, Hyper3dError> {
|
||
let response = http_client
|
||
.post(format!("{}{}", settings.base_url, path))
|
||
.header(
|
||
header::AUTHORIZATION,
|
||
format!("Bearer {}", settings.api_key),
|
||
)
|
||
.header(header::ACCEPT, "application/json")
|
||
.header(header::CONTENT_TYPE, "application/json")
|
||
.json(&body)
|
||
.send()
|
||
.await
|
||
.map_err(|error| map_reqwest_error(failure_context, path, error))?;
|
||
parse_hyper3d_response(response, failure_context).await
|
||
}
|
||
|
||
async fn parse_hyper3d_response(
|
||
response: reqwest::Response,
|
||
failure_context: &str,
|
||
) -> Result<Value, Hyper3dError> {
|
||
let status = response.status();
|
||
let raw_text = response.text().await.map_err(|error| {
|
||
Hyper3dError::request(
|
||
format!("{failure_context}:读取上游响应失败:{error}"),
|
||
None,
|
||
false,
|
||
false,
|
||
false,
|
||
true,
|
||
None,
|
||
None,
|
||
)
|
||
})?;
|
||
if !status.is_success() {
|
||
return Err(Hyper3dError::upstream(
|
||
parse_api_error_message(&raw_text, failure_context),
|
||
status.as_u16(),
|
||
truncate_raw(&raw_text),
|
||
));
|
||
}
|
||
|
||
serde_json::from_str::<Value>(&raw_text).map_err(|error| {
|
||
Hyper3dError::response_parse(
|
||
format!("{failure_context}:解析上游 JSON 失败:{error}"),
|
||
truncate_raw(&raw_text),
|
||
)
|
||
})
|
||
}
|
||
|
||
fn map_reqwest_error(failure_context: &str, endpoint: &str, error: reqwest::Error) -> Hyper3dError {
|
||
Hyper3dError::request(
|
||
format!("{failure_context}:{error}"),
|
||
Some(endpoint.to_string()),
|
||
error.is_timeout(),
|
||
error.is_connect(),
|
||
error.is_request(),
|
||
error.is_body(),
|
||
error.status().map(|status| status.as_u16()),
|
||
Error::source(&error).map(ToString::to_string),
|
||
)
|
||
}
|
||
|
||
fn truncate_raw(raw_text: &str) -> String {
|
||
raw_text.chars().take(800).collect()
|
||
}
|