1use http::{HeaderMap, HeaderName, HeaderValue};
2use std::time::Duration;
3
4#[derive(Clone, Debug, PartialEq, Eq)]
6pub struct BasicAuth {
7 pub username: String,
8 pub password: String,
9}
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub struct RetryPolicy {
14 pub max_retries: usize,
15 pub initial_backoff: Duration,
16}
17
18impl RetryPolicy {
19 pub fn new(max_retries: usize, initial_backoff: Duration) -> Self {
21 Self {
22 max_retries,
23 initial_backoff,
24 }
25 }
26}
27
28impl Default for RetryPolicy {
29 fn default() -> Self {
30 Self {
31 max_retries: 2,
32 initial_backoff: Duration::from_millis(200),
33 }
34 }
35}
36
37#[derive(Clone, Debug)]
39pub struct ClientConfig {
40 pub endpoint: String,
41 pub api_version: Option<String>,
42 pub basic_auth: Option<BasicAuth>,
43 pub timeout: Duration,
44 pub retry_policy: RetryPolicy,
45 pub headers: HeaderMap,
46}
47
48impl ClientConfig {
49 pub fn new(endpoint: impl Into<String>) -> Self {
51 Self {
52 endpoint: endpoint.into(),
53 api_version: None,
54 basic_auth: None,
55 timeout: Duration::from_secs(15),
56 retry_policy: RetryPolicy::default(),
57 headers: HeaderMap::new(),
58 }
59 }
60
61 pub fn with_api_version(mut self, version: impl Into<String>) -> Self {
63 self.api_version = Some(version.into());
64 self
65 }
66
67 pub fn with_basic_auth(
69 mut self,
70 username: impl Into<String>,
71 password: impl Into<String>,
72 ) -> Self {
73 self.basic_auth = Some(BasicAuth {
74 username: username.into(),
75 password: password.into(),
76 });
77 self
78 }
79
80 pub fn with_timeout(mut self, timeout: Duration) -> Self {
82 self.timeout = timeout;
83 self
84 }
85
86 pub fn with_retry_policy(mut self, retry_policy: RetryPolicy) -> Self {
88 self.retry_policy = retry_policy;
89 self
90 }
91
92 pub fn without_retries(mut self) -> Self {
94 self.retry_policy = RetryPolicy::new(0, Duration::ZERO);
95 self
96 }
97
98 pub fn with_header(
100 mut self,
101 name: impl AsRef<str>,
102 value: impl AsRef<str>,
103 ) -> Result<Self, http::Error> {
104 let name = HeaderName::from_bytes(name.as_ref().as_bytes())?;
105 let value = HeaderValue::from_str(value.as_ref())?;
106 self.headers.insert(name, value);
107 Ok(self)
108 }
109}