magnetar/magnetar_sdk/src/client/reqwest.rs

113 lines
3.6 KiB
Rust

use crate::endpoints::{Endpoint, ErrorKind, ResponseError};
use crate::Client;
use http::header::{CONTENT_TYPE, USER_AGENT};
use http::{HeaderMap, HeaderValue, Method, StatusCode};
use serde::de::DeserializeOwned;
use serde::Serialize;
pub struct ReqwestClient {
client: reqwest::Client,
base_url: String,
}
impl ReqwestClient {
pub fn new(base_url: &str, application: &str) -> Self {
let mut headers = HeaderMap::new();
headers.insert(
CONTENT_TYPE,
HeaderValue::from_str("application/json").unwrap(),
);
headers.insert(USER_AGENT, HeaderValue::from_str(application).unwrap());
let client_builder = reqwest::ClientBuilder::new().default_headers(headers);
#[cfg(not(target_arch = "wasm32"))]
let client_builder = { client_builder.https_only(true) };
let client = client_builder.build().unwrap();
ReqwestClient {
client,
base_url: base_url.to_string(),
}
}
}
#[async_trait::async_trait(?Send)]
impl Client for ReqwestClient {
fn base_url(&self) -> &str {
&self.base_url
}
async fn call<'a, I, O, E>(
&self,
endpoint: &E,
data: &I,
path_params: &impl AsRef<[(&'a str, &'a str)]>,
) -> Result<O, ResponseError>
where
I: Serialize + DeserializeOwned + Send + 'static,
O: Serialize + DeserializeOwned + Send + 'static,
E: Endpoint<Request = I, Response = O> + Send + 'static,
{
let url = endpoint.template_path(self.base_url(), path_params);
let req = self.client.request(E::METHOD, &url);
let req = if E::METHOD == Method::GET {
req.query(&data)
} else {
req.json(&data)
};
let response = req.send().await.map_err(|e| ResponseError {
kind: ErrorKind::Other,
code: "ReqwestClient:Fail".to_string(),
message: e.to_string(),
status: None,
})?;
let status = response.status();
if status.is_client_error() || status.is_server_error() {
match response.json::<ResponseError>().await {
Ok(res) => Err(res),
Err(e) => Err(ResponseError {
kind: ErrorKind::ApiError,
code: "ReqwestClient:ApiGenericError".to_string(),
message: e.to_string(),
status: Some(status.as_u16()),
}),
}
} else if status.is_success() {
if status == StatusCode::NO_CONTENT.as_u16() {
return if let Some(val) = E::default_response() {
Ok(val)
} else {
Err(ResponseError {
kind: ErrorKind::ApiError,
code: "ReqwestClient:ResponseError204".to_string(),
message: "Response is empty".to_string(),
status: Some(status.as_u16()),
})
};
}
let data = response.json::<O>().await.map_err(|e| ResponseError {
kind: ErrorKind::ApiError,
code: "ReqwestClient:JsonError".to_string(),
message: e.to_string(),
status: Some(status.as_u16()),
})?;
Ok(data)
} else {
Err(ResponseError {
kind: ErrorKind::ApiError,
code: "ReqwestClient:ApiUnknownStatusError".to_string(),
message: status.to_string(),
status: Some(status.as_u16()),
})
}
}
}