1use nextcloud_sdk_core::{ServerUrl, UrlError};
4
5use crate::GoaError;
6
7pub fn parse_webdav_url(uri: &str) -> Result<ServerUrl, GoaError> {
19 let uri = uri.trim();
20 if uri.is_empty() {
21 return Err(GoaError::Url(UrlError::MissingHost));
22 }
23
24 let normalized = if let Some(rest) = uri.strip_prefix("davs://") {
26 format!("https://{rest}")
27 } else if let Some(rest) = uri.strip_prefix("dav://") {
28 format!("http://{rest}")
29 } else {
30 uri.to_owned()
31 };
32
33 let base = match normalized.find("/remote.php") {
35 Some(idx) => &normalized[..idx],
36 None => &normalized,
37 };
38
39 let trimmed = base.trim_end_matches('/');
40 let server_url = ServerUrl::parse(trimmed)?;
41 Ok(server_url)
42}
43
44#[cfg(test)]
45mod tests {
46 use super::parse_webdav_url;
47 use crate::GoaError;
48
49 #[test]
50 fn parses_standard_webdav_endpoint() {
51 let parsed = parse_webdav_url("https://cloud.example.com/remote.php/webdav/").unwrap();
52 assert_eq!(parsed.as_str(), "https://cloud.example.com");
53 assert_eq!(parsed.authority(), "cloud.example.com");
54 assert_eq!(parsed.path_prefix(), "");
55 }
56
57 #[test]
58 fn parses_dav_files_endpoint() {
59 let parsed =
60 parse_webdav_url("https://cloud.example.com/remote.php/dav/files/alice/").unwrap();
61 assert_eq!(parsed.as_str(), "https://cloud.example.com");
62 }
63
64 #[test]
65 fn parses_davs_scheme() {
66 let parsed = parse_webdav_url("davs://cloud.example.com/remote.php/webdav/").unwrap();
67 assert_eq!(parsed.as_str(), "https://cloud.example.com");
68 assert!(parsed.is_https());
69 }
70
71 #[test]
72 fn parses_dav_insecure_scheme() {
73 let parsed = parse_webdav_url("dav://insecure.example.com/remote.php/webdav/").unwrap();
74 assert_eq!(parsed.as_str(), "http://insecure.example.com");
75 assert!(!parsed.is_https());
76 }
77
78 #[test]
79 fn parses_custom_port_and_subdirectory() {
80 let parsed = parse_webdav_url("http://localhost:8080/nextcloud/remote.php/webdav").unwrap();
81 assert_eq!(parsed.as_str(), "http://localhost:8080/nextcloud");
82 assert_eq!(parsed.authority(), "localhost:8080");
83 assert_eq!(parsed.path_prefix(), "/nextcloud");
84 }
85
86 #[test]
87 fn parses_root_urls_without_remote_php() {
88 let parsed1 = parse_webdav_url("https://cloud.example.com/").unwrap();
89 assert_eq!(parsed1.as_str(), "https://cloud.example.com");
90
91 let parsed2 = parse_webdav_url("https://cloud.example.com").unwrap();
92 assert_eq!(parsed2.as_str(), "https://cloud.example.com");
93 }
94
95 #[test]
96 fn rejects_invalid_urls() {
97 assert!(matches!(parse_webdav_url(""), Err(GoaError::Url(_))));
98 assert!(matches!(
99 parse_webdav_url("cloud.example.com"),
100 Err(GoaError::Url(_))
101 ));
102 assert!(matches!(
103 parse_webdav_url("ftp://cloud.example.com"),
104 Err(GoaError::Url(_))
105 ));
106 }
107}