use std::fmt;
use std::time::Duration;
use reqwest::header::{HeaderMap, HeaderName, HeaderValue, ACCEPT};
use crate::interceptor::{RequestInterceptor, ResponseInterceptor};
use crate::retry::RetryPolicy;
pub struct ClientConfig {
pub timeout: Option<Duration>,
pub connect_timeout: Option<Duration>,
pub retry_policy: RetryPolicy,
pub request_interceptors: Vec<RequestInterceptor>,
pub response_interceptors: Vec<ResponseInterceptor>,
pub default_headers: HeaderMap,
pub cookie_store: bool,
pub enable_tracing: bool,
}
impl Default for ClientConfig {
fn default() -> Self {
let mut default_headers = HeaderMap::new();
default_headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
Self {
timeout: Some(Duration::from_secs(30)),
connect_timeout: Some(Duration::from_secs(10)),
retry_policy: RetryPolicy::default(),
request_interceptors: Vec::new(),
response_interceptors: Vec::new(),
default_headers,
cookie_store: false,
enable_tracing: false,
}
}
}
impl Clone for ClientConfig {
fn clone(&self) -> Self {
Self {
timeout: self.timeout,
connect_timeout: self.connect_timeout,
retry_policy: self.retry_policy.clone(),
request_interceptors: self.request_interceptors.clone(),
response_interceptors: self.response_interceptors.clone(),
default_headers: self.default_headers.clone(),
cookie_store: self.cookie_store,
enable_tracing: self.enable_tracing,
}
}
}
impl fmt::Debug for ClientConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ClientConfig")
.field("timeout", &self.timeout)
.field("connect_timeout", &self.connect_timeout)
.field("retry_policy", &self.retry_policy)
.field(
"request_interceptors",
&format!("[{} interceptor(s)]", self.request_interceptors.len()),
)
.field(
"response_interceptors",
&format!("[{} interceptor(s)]", self.response_interceptors.len()),
)
.field("default_headers", &self.default_headers)
.field("cookie_store", &self.cookie_store)
.field("enable_tracing", &self.enable_tracing)
.finish()
}
}
impl ClientConfig {
pub fn timeout(mut self, d: Duration) -> Self {
self.timeout = Some(d);
self
}
pub fn no_timeout(mut self) -> Self {
self.timeout = None;
self
}
pub fn connect_timeout(mut self, d: Duration) -> Self {
self.connect_timeout = Some(d);
self
}
pub fn no_connect_timeout(mut self) -> Self {
self.connect_timeout = None;
self
}
pub fn retry_policy(mut self, policy: RetryPolicy) -> Self {
self.retry_policy = policy;
self
}
pub fn request_interceptor(mut self, interceptor: RequestInterceptor) -> Self {
self.request_interceptors.push(interceptor);
self
}
pub fn response_interceptor(mut self, interceptor: ResponseInterceptor) -> Self {
self.response_interceptors.push(interceptor);
self
}
pub fn default_header(mut self, name: HeaderName, value: HeaderValue) -> Self {
self.default_headers.insert(name, value);
self
}
pub fn bearer_auth(self, token: &str) -> Self {
let value = HeaderValue::from_str(&format!("Bearer {token}"))
.expect("bearer token contains invalid header characters");
self.default_header(http::header::AUTHORIZATION, value)
}
pub fn cookie_store(mut self, enabled: bool) -> Self {
self.cookie_store = enabled;
self
}
pub fn enable_tracing(mut self) -> Self {
self.enable_tracing = true;
self
}
}