fhir_sdk/client/
builder.rs1use std::marker::PhantomData;
4
5use reqwest::Url;
6
7use super::{Client, Error, LoginManager, RequestSettings, auth::AuthCallback};
8use crate::version::{DefaultVersion, FhirVersion};
9
10const DEFAULT_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
12
13pub struct ClientBuilder<Version = DefaultVersion, ACB = ()> {
15 base_url: Option<Url>,
17 client: Option<reqwest::Client>,
19 user_agent: Option<String>,
21 request_settings: Option<RequestSettings>,
23 auth_callback: Option<ACB>,
25
26 error_on_version_mismatch: bool,
29 error_on_origin_mismatch: bool,
34
35 version: PhantomData<Version>,
37}
38
39impl<V, ACB> Default for ClientBuilder<V, ACB>
40where
41 V: FhirVersion,
42{
43 fn default() -> Self {
44 Self {
45 base_url: None,
46 client: None,
47 user_agent: None,
48 request_settings: None,
49 auth_callback: None,
50 error_on_version_mismatch: true,
51 error_on_origin_mismatch: true,
52 version: PhantomData,
53 }
54 }
55}
56
57impl<V, ACB> ClientBuilder<V, ACB>
58where
59 V: FhirVersion,
60{
61 #[must_use]
63 pub fn base_url(mut self, base_url: Url) -> Self {
64 self.base_url = Some(base_url);
65 self
66 }
67
68 #[must_use]
70 pub fn client(mut self, client: reqwest::Client) -> Self {
71 self.client = Some(client);
72 self
73 }
74
75 #[must_use]
78 pub fn user_agent(mut self, user_agent: String) -> Self {
79 self.user_agent = Some(user_agent);
80 self
81 }
82
83 #[must_use]
85 pub fn request_settings(mut self, settings: RequestSettings) -> Self {
86 self.request_settings = Some(settings);
87 self
88 }
89
90 #[must_use]
104 pub fn auth_callback<LM>(self, login_manager: LM) -> ClientBuilder<V, LM>
105 where
106 LM: LoginManager + 'static,
107 {
108 ClientBuilder {
109 base_url: self.base_url,
110 client: self.client,
111 user_agent: self.user_agent,
112 request_settings: self.request_settings,
113 auth_callback: Some(login_manager),
114 version: self.version,
115 error_on_version_mismatch: self.error_on_version_mismatch,
116 error_on_origin_mismatch: self.error_on_origin_mismatch,
117 }
118 }
119
120 #[must_use]
123 pub const fn allow_version_mismatch(mut self) -> Self {
124 self.error_on_version_mismatch = false;
125 self
126 }
127
128 #[must_use]
133 pub const fn allow_origin_mismatch(mut self) -> Self {
134 self.error_on_origin_mismatch = false;
135 self
136 }
137
138 pub fn build(self) -> Result<Client<V>, Error>
140 where
141 ACB: LoginManager + 'static,
142 {
143 let Some(base_url) = self.base_url else {
144 return Err(Error::BuilderMissingField("base_url"));
145 };
146 if base_url.cannot_be_a_base() {
147 return Err(Error::UrlCannotBeBase);
148 }
149
150 let client = match self.client {
151 Some(client) => client,
152 None => {
153 let user_agent = self.user_agent.as_deref().unwrap_or(DEFAULT_USER_AGENT);
154 reqwest::Client::builder().user_agent(user_agent).build()?
155 }
156 };
157
158 let request_settings = self.request_settings.unwrap_or_default();
159
160 let data = super::ClientData {
161 base_url,
162 client,
163 request_settings: std::sync::Mutex::new(request_settings),
164 auth_callback: tokio::sync::Mutex::new(self.auth_callback.map(AuthCallback::new)),
165 error_on_version_mismatch: self.error_on_version_mismatch,
166 error_on_origin_mismatch: self.error_on_origin_mismatch,
167 };
168 Ok(Client::from(data))
169 }
170}
171
172impl<V, ACB> Clone for ClientBuilder<V, ACB>
173where
174 ACB: Clone,
175{
176 fn clone(&self) -> Self {
177 Self {
178 base_url: self.base_url.clone(),
179 client: self.client.clone(),
180 user_agent: self.user_agent.clone(),
181 request_settings: self.request_settings.clone(),
182 auth_callback: self.auth_callback.clone(),
183 version: self.version,
184 error_on_version_mismatch: self.error_on_version_mismatch,
185 error_on_origin_mismatch: self.error_on_origin_mismatch,
186 }
187 }
188}
189
190impl<V, ACB> std::fmt::Debug for ClientBuilder<V, ACB> {
191 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
192 f.debug_struct("ClientBuilder")
193 .field("base_url", &self.base_url)
194 .field("client", &self.client)
195 .field("user_agent", &self.user_agent)
196 .field("request_settings", &self.request_settings)
197 .field("auth_callback", &self.auth_callback.as_ref().map(|_| "<login_manager>"))
198 .field("error_on_version_mismatch", &self.error_on_version_mismatch)
199 .field("error_on_origin_mismatch", &self.error_on_origin_mismatch)
200 .field("version", &std::any::type_name::<V>())
201 .finish()
202 }
203}