From def17b6218a559b432a1a8555159843c85f92c92 Mon Sep 17 00:00:00 2001 From: daladim Date: Sun, 21 Mar 2021 23:52:42 +0100 Subject: [PATCH] Wrapped Url, username and password together --- src/client.rs | 37 +++++++++++++++++-------------------- src/lib.rs | 1 + src/resource.rs | 26 ++++++++++++++++++++++++++ src/utils.rs | 7 ------- 4 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 src/resource.rs diff --git a/src/client.rs b/src/client.rs index 31b08f4..5bab672 100644 --- a/src/client.rs +++ b/src/client.rs @@ -11,6 +11,7 @@ use reqwest::header::CONTENT_TYPE; use minidom::Element; use url::Url; +use crate::resource::Resource; use crate::utils::{find_elem, find_elems}; use crate::calendar::remote_calendar::RemoteCalendar; use crate::calendar::CalendarId; @@ -49,9 +50,7 @@ static CAL_BODY: &str = r#" /// A CalDAV source that fetches its data from a CalDAV server pub struct Client { - url: Url, - username: String, - password: String, + resource: Resource, /// The interior mutable part of a Client. /// This data may be retrieved once and then cached @@ -61,8 +60,8 @@ pub struct Client { #[derive(Default)] struct CachedReplies { - principal: Option, - calendar_home_set: Option, + principal: Option, + calendar_home_set: Option, calendars: Option>>>, } @@ -72,22 +71,20 @@ impl Client { let url = Url::parse(url.as_ref())?; Ok(Self{ - url, - username: username.to_string(), - password: password.to_string(), + resource: Resource::new(url, username.to_string(), password.to_string()), cached_replies: Mutex::new(CachedReplies::default()), }) } - async fn sub_request(&self, url: &Url, body: String, depth: u32) -> Result> { + async fn sub_request(&self, resource: &Resource, body: String, depth: u32) -> Result> { let method = Method::from_bytes(b"PROPFIND") .expect("cannot create PROPFIND method."); let res = reqwest::Client::new() - .request(method, url.as_str()) + .request(method, resource.url().clone()) .header("Depth", depth) .header(CONTENT_TYPE, "application/xml") - .basic_auth(self.username.clone(), Some(self.password.clone())) + .basic_auth(resource.username(), Some(resource.password())) .body(body) .send() .await?; @@ -95,8 +92,8 @@ impl Client { Ok(text) } - async fn sub_request_and_process(&self, url: &Url, body: String, items: &[&str]) -> Result> { - let text = self.sub_request(url, body, 0).await?; + async fn sub_request_and_process(&self, resource: &Resource, body: String, items: &[&str]) -> Result> { + let text = self.sub_request(resource, body, 0).await?; let mut current_element: &Element = &text.parse()?; for item in items { @@ -109,13 +106,13 @@ impl Client { } /// Return the Principal URL, or fetch it from server if not known yet - async fn get_principal(&self) -> Result> { + async fn get_principal(&self) -> Result> { if let Some(p) = &self.cached_replies.lock().unwrap().principal { return Ok(p.clone()); } - let href = self.sub_request_and_process(&self.url, DAVCLIENT_BODY.into(), &["current-user-principal", "href"]).await?; - let principal_url = crate::utils::build_url(&self.url, &href); + let href = self.sub_request_and_process(&self.resource, DAVCLIENT_BODY.into(), &["current-user-principal", "href"]).await?; + let principal_url = self.resource.combine(&href); self.cached_replies.lock().unwrap().principal = Some(principal_url.clone()); log::debug!("Principal URL is {}", href); @@ -123,16 +120,16 @@ impl Client { } /// Return the Homeset URL, or fetch it from server if not known yet - async fn get_cal_home_set(&self) -> Result> { + async fn get_cal_home_set(&self) -> Result> { if let Some(h) = &self.cached_replies.lock().unwrap().calendar_home_set { return Ok(h.clone()); } let principal_url = self.get_principal().await?; let href = self.sub_request_and_process(&principal_url, HOMESET_BODY.into(), &["calendar-home-set", "href"]).await?; - let chs_url = crate::utils::build_url(&self.url, &href); + let chs_url = self.resource.combine(&href); self.cached_replies.lock().unwrap().calendar_home_set = Some(chs_url.clone()); - log::debug!("Calendar home set URL is {:?}", chs_url.path()); + log::debug!("Calendar home set URL is {:?}", href); Ok(chs_url) } @@ -182,7 +179,7 @@ impl Client { Some(h) => h.text(), }; - let this_calendar_url = crate::utils::build_url(&self.url, &calendar_href); + let this_calendar_url = self.resource.combine(&calendar_href); let supported_components = match crate::calendar::SupportedComponents::try_from(el_supported_comps.clone()) { Err(err) => { diff --git a/src/lib.rs b/src/lib.rs index e7f6644..a328e95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,3 +26,4 @@ pub mod cache; pub mod settings; pub mod utils; +pub mod resource; diff --git a/src/resource.rs b/src/resource.rs new file mode 100644 index 0000000..1914333 --- /dev/null +++ b/src/resource.rs @@ -0,0 +1,26 @@ +use url::Url; + +/// Just a wrapper around a URL and credentials +#[derive(Clone)] +pub struct Resource { + url: Url, + username: String, + password: String, +} + +impl Resource { + pub fn new(url: Url, username: String, password: String) -> Self { + Self { url, username, password } + } + + pub fn url(&self) -> &Url { &self.url } + pub fn username(&self) -> &String { &self.username } + pub fn password(&self) -> &String { &self.password } + + /// Build a new Resource by keeping the same credentials, scheme and server from `base` but changing the path part + pub fn combine(&self, new_path: &str) -> Resource { + let mut built = (*self).clone(); + built.url.set_path(&new_path); + built + } +} diff --git a/src/utils.rs b/src/utils.rs index fad40d9..00ea294 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -46,13 +46,6 @@ pub fn find_elem>(root: &Element, searched_name: S) -> Option<&Ele None } -/// Build a new Url by keeping the same scheme and server from `base` but changing the path part -pub fn build_url(base: &Url, new_path: &str) -> Url { - let mut built = base.clone(); - built.set_path(&new_path); - built -} - pub fn print_xml(element: &Element) { use std::io::Write;