use crate::errors::response_error::RequestError;
use crate::utils::credentials_manager::CredentialsManager;
use crate::utils::network::http_client::HttpClient;
use hyper::body::Bytes;
use hyper::{Body, Request};
use serde::de::DeserializeOwned;
use std::collections::HashMap;
use url::Url;
pub(crate) async fn fetch_endpoint<T: HttpClient, D: DeserializeOwned>(
credentials_manager: &CredentialsManager,
http_client: &T,
uri: &Url,
method: &str,
body: &str,
headers: &HashMap<String, String>,
) -> Result<D, RequestError> {
let raw_result =
fetch_endpoint_raw(credentials_manager, http_client, uri, method, body, headers).await?;
serde_json::from_slice(&raw_result).map_err(|e| e.into())
}
async fn fetch_endpoint_raw<T: HttpClient>(
credentials_manager: &CredentialsManager,
http_client: &T,
uri: &Url,
method: &str,
body: &str,
headers: &HashMap<String, String>,
) -> Result<Bytes, RequestError> {
let auth_headers = credentials_manager.get_auth_headers().await?;
let headers = headers
.iter()
.chain(auth_headers.iter())
.map(|(key, value)| (key.clone(), value.clone()))
.collect::<HashMap<String, String>>();
let request = build_request(uri, method, body, &headers)?;
let response = http_client.request(request).await?;
let status = response.status();
let body = hyper::body::to_bytes(response.into_body()).await?;
if !status.is_success() {
return Err(RequestError::from((status.as_u16(), body)));
}
Ok(body)
}
fn build_request(
uri: &Url,
method: &str,
body: &str,
headers: &HashMap<String, String>,
) -> Result<Request<Body>, RequestError> {
let mut request = hyper::Request::builder()
.method(method)
.uri(uri.as_str())
.body(hyper::Body::from(body.to_string()))
.map_err(|e| RequestError::ParseError(e.to_string()))?;
headers.iter().for_each(|(key, value)| {
let header_key = hyper::header::HeaderName::from_bytes(key.as_bytes());
let header_key = match header_key {
Ok(header_key) => header_key,
Err(_) => return,
};
let header_value = hyper::header::HeaderValue::from_str(value);
let header_value = match header_value {
Ok(header_value) => header_value,
Err(_) => return,
};
request.headers_mut().append(header_key, header_value);
});
Ok(request)
}