diff --git a/src/webdav_xml_parser.rs b/src/webdav_xml_parser.rs index 45ed279..6fcc17d 100644 --- a/src/webdav_xml_parser.rs +++ b/src/webdav_xml_parser.rs @@ -83,7 +83,13 @@ pub fn parse_propfind_response(xml_text: &str) -> Result> { resp.content_type = Some(text.trim().to_string()); } "getetag" => { - resp.etag = Some(text.trim().to_string()); + // Normalize ETag by removing quotes and weak ETag prefix + let etag = text.trim(); + let normalized = etag + .trim_start_matches("W/") + .trim_matches('"') + .to_string(); + resp.etag = Some(normalized); } "status" if in_propstat => { // Check if status is 200 OK diff --git a/tests/webdav_sync_tests.rs b/tests/webdav_sync_tests.rs index 24fae0c..71e1954 100644 --- a/tests/webdav_sync_tests.rs +++ b/tests/webdav_sync_tests.rs @@ -182,6 +182,26 @@ fn test_etag_change_detection() { assert_eq!(normalized_etag, old_etag); } +#[test] +fn test_etag_normalization() { + // Test various ETag formats that WebDAV servers might return + let test_cases = vec![ + ("abc123", "abc123"), // Plain ETag + ("\"abc123\"", "abc123"), // Quoted ETag + ("W/\"abc123\"", "abc123"), // Weak ETag + ("\"abc-123-def\"", "abc-123-def"), // Quoted with dashes + ("W/\"abc-123-def\"", "abc-123-def"), // Weak ETag with dashes + ]; + + for (input, expected) in test_cases { + let normalized = input + .trim_start_matches("W/") + .trim_matches('"'); + assert_eq!(normalized, expected, + "Failed to normalize ETag: {} -> expected {}", input, expected); + } +} + #[test] fn test_path_normalization() { let test_paths = vec![