use reqwest::{Client, RequestBuilder};
use crate::client::ClientError;
use crate::options::TransportOptions;
pub fn build_http_client(transport_options: &TransportOptions) -> Result<Client, reqwest::Error> {
let mut builder = Client::builder();
match transport_options {
TransportOptions::Http { timeout, proxy, .. } => {
if let Some(t) = timeout {
builder = builder.timeout(*t);
}
if let Some(proxy_url) = proxy {
if let Ok(p) = reqwest::Proxy::all(proxy_url) {
builder = builder.proxy(p);
}
}
}
}
builder.build()
}
pub fn add_extra_headers(
mut request: RequestBuilder,
transport_options: &TransportOptions,
) -> RequestBuilder {
match transport_options {
TransportOptions::Http { headers, .. } => {
if let Some(h) = headers {
for (key, value) in h {
request = request.header(key, value);
}
}
}
}
request
}
pub trait RequestBuilderExt {
fn json_logged<T: serde::Serialize + ?Sized>(self, json: &T) -> Self;
}
impl RequestBuilderExt for RequestBuilder {
fn json_logged<T: serde::Serialize + ?Sized>(self, json: &T) -> Self {
if let Ok(req_body) = serde_json::to_string_pretty(json) {
tracing::debug!("API request body ({} bytes):\n{}", req_body.len(), req_body);
}
self.json(json)
}
}
#[async_trait::async_trait]
pub trait ResponseExt {
async fn text_logged(self) -> Result<String, reqwest::Error>;
async fn json_logged<T: serde::de::DeserializeOwned>(self) -> Result<T, ClientError>;
}
#[async_trait::async_trait]
impl ResponseExt for reqwest::Response {
async fn text_logged(self) -> Result<String, reqwest::Error> {
let text = self.text().await?;
tracing::debug!("API response ({} bytes):\n{}", text.len(), text);
Ok(text)
}
async fn json_logged<T: serde::de::DeserializeOwned>(self) -> Result<T, ClientError> {
let bytes = self.bytes().await?;
if let Ok(text) = std::str::from_utf8(&bytes) {
tracing::debug!("API response ({} bytes):\n{}", text.len(), text);
}
serde_json::from_slice(&bytes).map_err(ClientError::from)
}
}