diff --git a/src/service/targets/autopulse.rs b/src/service/targets/autopulse.rs index 60e975c3..286ab495 100644 --- a/src/service/targets/autopulse.rs +++ b/src/service/targets/autopulse.rs @@ -1,6 +1,7 @@ use crate::{ db::models::ScanEvent, settings::{auth::Auth, target::TargetProcess}, + utils::get_url::get_url, }; use reqwest::header; use serde::Deserialize; @@ -35,7 +36,7 @@ impl Autopulse { async fn scan(&self, ev: &ScanEvent) -> anyhow::Result<()> { let client = self.get_client()?; - let mut url = url::Url::parse(&self.url)?.join("/triggers/manual")?; + let mut url = get_url(&self.url)?.join("triggers/manual")?; url.query_pairs_mut().append_pair("path", &ev.file_path); diff --git a/src/service/targets/emby.rs b/src/service/targets/emby.rs index 2b8854cf..2679d6cf 100644 --- a/src/service/targets/emby.rs +++ b/src/service/targets/emby.rs @@ -1,4 +1,4 @@ -use crate::{db::models::ScanEvent, settings::target::TargetProcess}; +use crate::{db::models::ScanEvent, settings::target::TargetProcess, utils::get_url::get_url}; use anyhow::Context; use reqwest::header; use serde::{Deserialize, Serialize}; @@ -117,20 +117,12 @@ impl Emby { .map_err(Into::into) } - fn get_url(&self) -> anyhow::Result { - let url = if self.url.ends_with('/') { - self.url.clone() - } else { - format!("{}/", self.url) - }; - - url::Url::parse(&url).map_err(Into::into) - } - async fn libraries(&self) -> anyhow::Result> { let client = self.get_client()?; - let url = self.get_url()?.join("Library/VirtualFolders")?.to_string(); + let url = get_url(&self.url)? + .join("Library/VirtualFolders")? + .to_string(); let res = client.get(&url).send().await?; let status = res.status(); @@ -166,7 +158,7 @@ impl Emby { async fn _get_item(&self, library: &Library, path: &str) -> anyhow::Result> { let client = self.get_client()?; - let mut url = self.get_url()?.join("Items")?; + let mut url = get_url(&self.url)?.join("Items")?; url.query_pairs_mut().append_pair("Recursive", "true"); url.query_pairs_mut().append_pair("Fields", "Path"); @@ -220,7 +212,7 @@ impl Emby { let limit = 1000; let client = self.get_client()?; - let mut url = self.get_url()?.join("Items")?; + let mut url = get_url(&self.url)?.join("Items")?; url.query_pairs_mut().append_pair("Recursive", "true"); url.query_pairs_mut().append_pair("Fields", "Path"); @@ -319,7 +311,9 @@ impl Emby { // not as effective as refreshing the item, but good enough async fn scan(&self, ev: &[&ScanEvent]) -> anyhow::Result<()> { let client = self.get_client()?; - let url = self.get_url()?.join("Library/Media/Updated")?.to_string(); + let url = get_url(&self.url)? + .join("Library/Media/Updated")? + .to_string(); let updates = ev .iter() @@ -354,9 +348,7 @@ impl Emby { async fn refresh_item(&self, item: &Item) -> anyhow::Result<()> { let client = self.get_client()?; - let mut url = self - .get_url()? - .join(&format!("Items/{}/Refresh", item.id))?; + let mut url = get_url(&self.url)?.join(&format!("Items/{}/Refresh", item.id))?; url.query_pairs_mut().append_pair( "metadataRefreshMode", diff --git a/src/service/targets/fileflows.rs b/src/service/targets/fileflows.rs index 01642eee..46549b76 100644 --- a/src/service/targets/fileflows.rs +++ b/src/service/targets/fileflows.rs @@ -1,4 +1,4 @@ -use crate::{db::models::ScanEvent, settings::target::TargetProcess}; +use crate::{db::models::ScanEvent, settings::target::TargetProcess, utils::get_url::get_url}; use anyhow::Context; use reqwest::header; use serde::{Deserialize, Serialize}; @@ -97,7 +97,7 @@ impl FileFlows { async fn get_libraries(&self) -> anyhow::Result> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)?.join("/api/library")?; + let url = get_url(&self.url)?.join("api/library")?; let res = client.get(url.to_string()).send().await?; let status = res.status(); @@ -123,7 +123,7 @@ impl FileFlows { ) -> anyhow::Result> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)?.join("/api/library-file/search")?; + let url = get_url(&self.url)?.join("api/library-file/search")?; let req = FileFlowsSearchRequest { path: ev.file_path.clone(), @@ -151,7 +151,7 @@ impl FileFlows { async fn reprocess_library_filse(&self, evs: Vec<&FileFlowsLibraryFile>) -> anyhow::Result<()> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)?.join("/api/library-file/reprocess")?; + let url = get_url(&self.url)?.join("api/library-file/reprocess")?; let req = FileFlowsReprocessRequest { uids: evs.iter().map(|ev| ev.uid.clone()).collect(), @@ -181,7 +181,7 @@ impl FileFlows { ) -> anyhow::Result<()> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)?.join("/api/library-file/manually-add")?; + let url = get_url(&self.url)?.join("api/library-file/manually-add")?; let req = FileFlowsManuallyAddRequest { flow_uid: library.flow.as_ref().unwrap().uid.clone(), @@ -208,7 +208,7 @@ impl FileFlows { // async fn rescan_library(&self, libraries: &FileFlowsLibrary) -> anyhow::Result<()> { // let client = self.get_client()?; - // let url = url::Url::parse(&self.url)?.join("/api/library/rescan")?; + // let url = get_url(&self.url)?.join("/api/library/rescan")?; // let req = FileFlowsRescanLibraryRequest { // uids: vec![libraries.uid.clone()], @@ -228,7 +228,7 @@ impl FileFlows { // async fn scan(&self, ev: &ScanEvent, library: &FileFlowsLibrary) -> anyhow::Result<()> { // let client = self.get_client()?; - // let mut url = url::Url::parse(&self.url)?.join("/api/library-file/process-file")?; + // let mut url = get_url(&self.url)?.join("/api/library-file/process-file")?; // url.query_pairs_mut().append_pair("filename", &ev.file_path); diff --git a/src/service/targets/plex.rs b/src/service/targets/plex.rs index 913b8221..bc78cbd7 100644 --- a/src/service/targets/plex.rs +++ b/src/service/targets/plex.rs @@ -1,6 +1,6 @@ use std::path::Path; -use crate::{db::models::ScanEvent, settings::target::TargetProcess}; +use crate::{db::models::ScanEvent, settings::target::TargetProcess, utils::get_url::get_url}; use anyhow::Context; use reqwest::header; use serde::Deserialize; @@ -96,9 +96,7 @@ impl Plex { async fn libraries(&self) -> anyhow::Result> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)? - .join("/library/sections")? - .to_string(); + let url = get_url(&self.url)?.join("library/sections")?.to_string(); let res = client.get(&url).send().await?; let status = res.status(); @@ -138,8 +136,8 @@ impl Plex { // TODO: Change to get_items async fn get_item(&self, library: &Library, path: &str) -> anyhow::Result> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)? - .join(&format!("/library/sections/{}/all", library.key))? + let url = get_url(&self.url)? + .join(&format!("library/sections/{}/all", library.key))? .to_string(); let res = client.get(&url).send().await?; @@ -175,7 +173,7 @@ impl Plex { // async fn refresh_library(&self, library: &str) -> anyhow::Result<()> { // let client = self.get_client()?; // let mut url = - // url::Url::parse(&self.url)?.join(&format!("/library/sections/{}/refresh", library))?; + // get_url(&self.url)?.join(&format!("/library/sections/{}/refresh", library))?; // url.query_pairs_mut().append_pair("force", "1"); @@ -192,7 +190,7 @@ impl Plex { // async fn analyze_library(&self, library: &str) -> anyhow::Result<()> { // let client = self.get_client()?; // let url = - // url::Url::parse(&self.url)?.join(&format!("/library/sections/{}/analyze", library))?; + // get_url(&self.url)?.join(&format!("/library/sections/{}/analyze", library))?; // let res = client.put(url.to_string()).send().await?; @@ -206,7 +204,7 @@ impl Plex { async fn refresh_item(&self, key: &str) -> anyhow::Result<()> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)?.join(&format!("{}/refresh", key))?; + let url = get_url(&self.url)?.join(&format!("{}/refresh", key))?; let res = client.put(url.to_string()).send().await?; @@ -220,7 +218,7 @@ impl Plex { async fn analyze_item(&self, key: &str) -> anyhow::Result<()> { let client = self.get_client()?; - let url = url::Url::parse(&self.url)?.join(&format!("{}/analyze", key))?; + let url = get_url(&self.url)?.join(&format!("{}/analyze", key))?; let res = client.put(url.to_string()).send().await?; @@ -234,8 +232,8 @@ impl Plex { async fn scan(&self, ev: &ScanEvent, library: &Library) -> anyhow::Result<()> { let client = self.get_client()?; - let mut url = url::Url::parse(&self.url)? - .join(&format!("/library/sections/{}/refresh", library.key))?; + let mut url = + get_url(&self.url)?.join(&format!("library/sections/{}/refresh", library.key))?; let file_dir = std::path::Path::new(&ev.file_path) .parent() diff --git a/src/service/targets/tdarr.rs b/src/service/targets/tdarr.rs index 1264b5ef..b3a9c979 100644 --- a/src/service/targets/tdarr.rs +++ b/src/service/targets/tdarr.rs @@ -1,7 +1,7 @@ use reqwest::header; use serde::{Deserialize, Serialize}; -use crate::{db::models::ScanEvent, settings::target::TargetProcess}; +use crate::{db::models::ScanEvent, settings::target::TargetProcess, utils::get_url::get_url}; #[derive(Deserialize, Clone)] pub struct Tdarr { @@ -59,9 +59,7 @@ impl Tdarr { }, }; - let url = url::Url::parse(&self.url)? - .join("/api/v2/scan-files")? - .to_string(); + let url = get_url(&self.url)?.join("/api/v2/scan-files")?.to_string(); let res = client .post(&url) diff --git a/src/tests/utils/get_url.rs b/src/tests/utils/get_url.rs new file mode 100644 index 00000000..d5e11c44 --- /dev/null +++ b/src/tests/utils/get_url.rs @@ -0,0 +1,31 @@ +#[cfg(test)] +mod tests { + use crate::utils::get_url::get_url; + + #[test] + fn test_join_no_subpath() -> anyhow::Result<()> { + let url = "http://example.com".to_string(); + + let parsed = get_url(&url)?; + + assert_eq!(parsed.to_string(), "http://example.com/"); + assert_eq!(parsed.join("test")?.to_string(), "http://example.com/test"); + + Ok(()) + } + + #[test] + fn test_join_with_subpath() -> anyhow::Result<()> { + let url = "http://example.com/test".to_string(); + + let parsed = get_url(&url)?; + + assert_eq!(parsed.to_string(), "http://example.com/test/"); + assert_eq!( + parsed.join("test")?.to_string(), + "http://example.com/test/test" + ); + + Ok(()) + } +} diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index 07468e66..90ed41df 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -1,6 +1,7 @@ pub mod check_auth; pub mod checksum; pub mod generate_uuid; +pub mod get_url; pub mod join_path; pub mod rewrite; pub mod sify; diff --git a/src/utils/get_url.rs b/src/utils/get_url.rs new file mode 100644 index 00000000..7e1f18b3 --- /dev/null +++ b/src/utils/get_url.rs @@ -0,0 +1,10 @@ +use std::borrow::Cow; + +pub fn get_url(url: &str) -> anyhow::Result { + let url: Cow = if url.ends_with('/') { + Cow::Borrowed(url) + } else { + format!("{}/", url).into() + }; + url::Url::parse(&url).map_err(Into::into) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 376d0f3b..a382c3a3 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -7,6 +7,8 @@ pub mod generate_uuid; #[doc(hidden)] pub mod get_timestamp; #[doc(hidden)] +pub mod get_url; +#[doc(hidden)] pub mod join_path; #[doc(hidden)] pub mod logs;