use reqwest::header::{HeaderName, HeaderValue};
use serde::de::DeserializeOwned;
use crate::ClientConfig;
use crate::config::ServiceBase;
use crate::error::{ApiErrorResponse, ConfigError, RekaError, Result};
use crate::transport::request::RequestBuilder;
use crate::transport::sse;
#[derive(Clone)]
pub(crate) struct HttpTransport {
client: reqwest::Client,
}
impl HttpTransport {
pub(crate) fn new(config: &ClientConfig) -> Result<Self> {
let mut default_headers = config.default_headers.clone();
let api_key =
HeaderValue::from_str(&config.api_key).map_err(ConfigError::InvalidApiKeyHeader)?;
default_headers.insert(HeaderName::from_static("x-api-key"), api_key);
let client = reqwest::Client::builder()
.default_headers(default_headers)
.user_agent(config.user_agent.clone())
.timeout(config.timeout)
.connect_timeout(config.connect_timeout)
.build()
.map_err(crate::Client::map_transport_error)?;
Ok(Self { client })
}
pub(crate) fn request(
&self,
config: &ClientConfig,
service: ServiceBase,
method: reqwest::Method,
path: impl Into<String>,
) -> RequestBuilder {
let path = path.into();
let url = config.endpoint_url(service, &path);
RequestBuilder::new(self.client.request(method, url), path)
}
}
pub(crate) async fn parse_json_response<T>(response: reqwest::Response, path: String) -> Result<T>
where
T: DeserializeOwned,
{
let status = response.status();
let headers = response.headers().clone();
let body = response
.text()
.await
.map_err(crate::Client::map_transport_error)?;
if !status.is_success() {
let api_error = serde_json::from_str::<ApiErrorResponse>(&body).ok();
return Err(RekaError::http_status(
status, path, body, api_error, headers,
));
}
serde_json::from_str(&body).map_err(|source| RekaError::decode(path, body, source))
}
pub(crate) async fn parse_sse_response(
response: reqwest::Response,
path: String,
) -> Result<sse::EventStream> {
let status = response.status();
let headers = response.headers().clone();
if !status.is_success() {
let body = response
.text()
.await
.map_err(crate::Client::map_transport_error)?;
let api_error = serde_json::from_str::<ApiErrorResponse>(&body).ok();
return Err(RekaError::http_status(
status, path, body, api_error, headers,
));
}
Ok(sse::decode(response.bytes_stream()))
}