diff options
Diffstat (limited to 'third_party/rust/glean-core/src/upload')
-rw-r--r-- | third_party/rust/glean-core/src/upload/directory.rs | 78 | ||||
-rw-r--r-- | third_party/rust/glean-core/src/upload/mod.rs | 343 | ||||
-rw-r--r-- | third_party/rust/glean-core/src/upload/request.rs | 37 |
3 files changed, 368 insertions, 90 deletions
diff --git a/third_party/rust/glean-core/src/upload/directory.rs b/third_party/rust/glean-core/src/upload/directory.rs index a78bbf0bdb..706550fe6c 100644 --- a/third_party/rust/glean-core/src/upload/directory.rs +++ b/third_party/rust/glean-core/src/upload/directory.rs @@ -9,15 +9,28 @@ use std::fs::{self, File}; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::request::HeaderMap; use crate::{DELETION_REQUEST_PINGS_DIRECTORY, PENDING_PINGS_DIRECTORY}; /// A representation of the data extracted from a ping file, -/// this will contain the document_id, path, JSON encoded body of a ping and the persisted headers. -pub type PingPayload = (String, String, String, Option<HeaderMap>); +#[derive(Clone, Debug, Default)] +pub struct PingPayload { + /// The ping's doc_id. + pub document_id: String, + /// The path to upload the ping to. + pub upload_path: String, + /// The ping body as JSON-encoded string. + pub json_body: String, + /// HTTP headers to include in the upload request. + pub headers: Option<HeaderMap>, + /// Whether the ping body contains {client|ping}_info + pub body_has_info_sections: bool, + /// The ping's name. (Also likely in the upload_path.) + pub ping_name: String, +} /// A struct to hold the result of scanning all pings directories. #[derive(Clone, Debug, Default)] @@ -62,20 +75,28 @@ fn get_file_name_as_str(path: &Path) -> Option<&str> { } } +/// A ping's metadata, as (optionally) represented on disk. +/// +/// Anything that isn't the upload path or the ping body. +#[derive(Default, Deserialize, Serialize)] +pub struct PingMetadata { + /// HTTP headers to include when uploading the ping. + pub headers: Option<HeaderMap>, + /// Whether the body has {client|ping}_info sections. + pub body_has_info_sections: Option<bool>, + /// The name of the ping. + pub ping_name: Option<String>, +} + /// Processes a ping's metadata. /// /// The metadata is an optional third line in the ping file, /// currently it contains only additonal headers to be added to each ping request. /// Therefore, we will process the contents of this line /// and return a HeaderMap of the persisted headers. -fn process_metadata(path: &str, metadata: &str) -> Option<HeaderMap> { - #[derive(Deserialize)] - struct PingMetadata { - pub headers: HeaderMap, - } - +fn process_metadata(path: &str, metadata: &str) -> Option<PingMetadata> { if let Ok(metadata) = serde_json::from_str::<PingMetadata>(metadata) { - return Some(metadata.headers); + return Some(metadata); } else { log::warn!("Error while parsing ping metadata: {}", path); } @@ -171,8 +192,23 @@ impl PingDirectoryManager { if let (Some(Ok(path)), Some(Ok(body)), Ok(metadata)) = (lines.next(), lines.next(), lines.next().transpose()) { - let headers = metadata.and_then(|m| process_metadata(&path, &m)); - return Some((document_id.into(), path, body, headers)); + let PingMetadata { + headers, + body_has_info_sections, + ping_name, + } = metadata + .and_then(|m| process_metadata(&path, &m)) + .unwrap_or_default(); + let ping_name = + ping_name.unwrap_or_else(|| path.split('/').nth(3).unwrap_or("").into()); + return Some(PingPayload { + document_id: document_id.into(), + upload_path: path, + json_body: body, + headers, + body_has_info_sections: body_has_info_sections.unwrap_or(true), + ping_name, + }); } else { log::warn!( "Error processing ping file: {}. Ping file is not formatted as expected.", @@ -303,7 +339,7 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, true, true, vec![]); + let ping_type = PingType::new("test", true, true, true, true, vec![]); glean.register_ping_type(&ping_type); // Submit the ping to populate the pending_pings directory @@ -320,7 +356,8 @@ mod test { // Verify request was returned for the "test" ping let ping = &data.pending_pings[0].1; - let request_ping_type = ping.1.split('/').nth(3).unwrap(); + let request_ping_type = ping.upload_path.split('/').nth(3).unwrap(); + assert_eq!(request_ping_type, ping.ping_name); assert_eq!(request_ping_type, "test"); } @@ -329,7 +366,7 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, true, true, vec![]); + let ping_type = PingType::new("test", true, true, true, true, vec![]); glean.register_ping_type(&ping_type); // Submit the ping to populate the pending_pings directory @@ -352,7 +389,8 @@ mod test { // Verify request was returned for the "test" ping let ping = &data.pending_pings[0].1; - let request_ping_type = ping.1.split('/').nth(3).unwrap(); + let request_ping_type = ping.upload_path.split('/').nth(3).unwrap(); + assert_eq!(request_ping_type, ping.ping_name); assert_eq!(request_ping_type, "test"); // Verify that file was indeed deleted @@ -364,7 +402,7 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, true, true, vec![]); + let ping_type = PingType::new("test", true, true, true, true, vec![]); glean.register_ping_type(&ping_type); // Submit the ping to populate the pending_pings directory @@ -387,7 +425,8 @@ mod test { // Verify request was returned for the "test" ping let ping = &data.pending_pings[0].1; - let request_ping_type = ping.1.split('/').nth(3).unwrap(); + let request_ping_type = ping.upload_path.split('/').nth(3).unwrap(); + assert_eq!(request_ping_type, ping.ping_name); assert_eq!(request_ping_type, "test"); // Verify that file was indeed deleted @@ -414,7 +453,8 @@ mod test { // Verify request was returned for the "deletion-request" ping let ping = &data.deletion_request_pings[0].1; - let request_ping_type = ping.1.split('/').nth(3).unwrap(); + let request_ping_type = ping.upload_path.split('/').nth(3).unwrap(); + assert_eq!(request_ping_type, ping.ping_name); assert_eq!(request_ping_type, "deletion-request"); } } diff --git a/third_party/rust/glean-core/src/upload/mod.rs b/third_party/rust/glean-core/src/upload/mod.rs index d764dcd29e..e51a9d9508 100644 --- a/third_party/rust/glean-core/src/upload/mod.rs +++ b/third_party/rust/glean-core/src/upload/mod.rs @@ -30,6 +30,7 @@ use directory::{PingDirectoryManager, PingPayloadsByDirectory}; use policy::Policy; use request::create_date_header_value; +pub use directory::{PingMetadata, PingPayload}; pub use request::{HeaderMap, PingRequest}; pub use result::{UploadResult, UploadTaskAction}; @@ -322,21 +323,24 @@ impl PingUploadManager { /// /// Returns the `PingRequest` or `None` if unable to build, /// in which case it will delete the ping file and record an error. - fn build_ping_request( - &self, - glean: &Glean, - document_id: &str, - path: &str, - body: &str, - headers: Option<HeaderMap>, - ) -> Option<PingRequest> { + fn build_ping_request(&self, glean: &Glean, ping: PingPayload) -> Option<PingRequest> { + let PingPayload { + document_id, + upload_path: path, + json_body: body, + headers, + body_has_info_sections, + ping_name, + } = ping; let mut request = PingRequest::builder( &self.language_binding_name, self.policy.max_ping_body_size(), ) - .document_id(document_id) + .document_id(&document_id) .path(path) - .body(body); + .body(body) + .body_has_info_sections(body_has_info_sections) + .ping_name(ping_name); if let Some(headers) = headers { request = request.headers(headers); @@ -346,7 +350,7 @@ impl PingUploadManager { Ok(request) => Some(request), Err(e) => { log::warn!("Error trying to build ping request: {}", e); - self.directory_manager.delete_file(document_id); + self.directory_manager.delete_file(&document_id); // Record the error. // Currently the only possible error is PingBodyOverflow. @@ -362,23 +366,21 @@ impl PingUploadManager { } /// Enqueue a ping for upload. - pub fn enqueue_ping( - &self, - glean: &Glean, - document_id: &str, - path: &str, - body: &str, - headers: Option<HeaderMap>, - ) { + pub fn enqueue_ping(&self, glean: &Glean, ping: PingPayload) { let mut queue = self .queue .write() .expect("Can't write to pending pings queue."); + let PingPayload { + ref document_id, + upload_path: ref path, + .. + } = ping; // Checks if a ping with this `document_id` is already enqueued. if queue .iter() - .any(|request| request.document_id == document_id) + .any(|request| request.document_id.as_str() == document_id) { log::warn!( "Attempted to enqueue a duplicate ping {} at {}.", @@ -404,7 +406,7 @@ impl PingUploadManager { } log::trace!("Enqueuing ping {} at {}", document_id, path); - if let Some(request) = self.build_ping_request(glean, document_id, path, body, headers) { + if let Some(request) = self.build_ping_request(glean, ping) { queue.push_back(request) } } @@ -455,7 +457,7 @@ impl PingUploadManager { // Thus, we reverse the order of the pending pings vector, // so that we iterate in descending order (newest -> oldest). cached_pings.pending_pings.reverse(); - cached_pings.pending_pings.retain(|(file_size, (document_id, _, _, _))| { + cached_pings.pending_pings.retain(|(file_size, PingPayload {document_id, ..})| { pending_pings_count += 1; pending_pings_directory_size += file_size; @@ -493,14 +495,14 @@ impl PingUploadManager { // Enqueue the remaining pending pings and // enqueue all deletion-request pings. - let deletion_request_pings = cached_pings.deletion_request_pings.drain(..); - for (_, (document_id, path, body, headers)) in deletion_request_pings { - self.enqueue_ping(glean, &document_id, &path, &body, headers); - } - let pending_pings = cached_pings.pending_pings.drain(..); - for (_, (document_id, path, body, headers)) in pending_pings { - self.enqueue_ping(glean, &document_id, &path, &body, headers); - } + cached_pings + .deletion_request_pings + .drain(..) + .for_each(|(_, ping)| self.enqueue_ping(glean, ping)); + cached_pings + .pending_pings + .drain(..) + .for_each(|(_, ping)| self.enqueue_ping(glean, ping)); } } @@ -532,10 +534,8 @@ impl PingUploadManager { /// * `glean` - The Glean object holding the database. /// * `document_id` - The UUID of the ping in question. pub fn enqueue_ping_from_file(&self, glean: &Glean, document_id: &str) { - if let Some((doc_id, path, body, headers)) = - self.directory_manager.process_file(document_id) - { - self.enqueue_ping(glean, &doc_id, &path, &body, headers) + if let Some(ping) = self.directory_manager.process_file(document_id) { + self.enqueue_ping(glean, ping); } } @@ -883,7 +883,17 @@ mod test { let upload_manager = PingUploadManager::no_policy(dir.path()); // Enqueue a ping - upload_manager.enqueue_ping(&glean, &Uuid::new_v4().to_string(), PATH, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: Uuid::new_v4().to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }, + ); // Try and get the next request. // Verify request was returned @@ -900,7 +910,17 @@ mod test { // Enqueue a ping multiple times let n = 10; for _ in 0..n { - upload_manager.enqueue_ping(&glean, &Uuid::new_v4().to_string(), PATH, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: Uuid::new_v4().to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }, + ); } // Verify a request is returned for each submitted ping @@ -928,7 +948,17 @@ mod test { // Enqueue the max number of pings allowed per uploading window for _ in 0..max_pings_per_interval { - upload_manager.enqueue_ping(&glean, &Uuid::new_v4().to_string(), PATH, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: Uuid::new_v4().to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }, + ); } // Verify a request is returned for each submitted ping @@ -938,7 +968,17 @@ mod test { } // Enqueue just one more ping - upload_manager.enqueue_ping(&glean, &Uuid::new_v4().to_string(), PATH, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: Uuid::new_v4().to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }, + ); // Verify that we are indeed told to wait because we are at capacity match upload_manager.get_upload_task(&glean, false) { @@ -961,7 +1001,17 @@ mod test { // Enqueue a ping multiple times for _ in 0..10 { - upload_manager.enqueue_ping(&glean, &Uuid::new_v4().to_string(), PATH, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: Uuid::new_v4().to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }, + ); } // Clear the queue @@ -979,7 +1029,14 @@ mod test { let (mut glean, _t) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit the ping multiple times @@ -1011,7 +1068,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit the ping multiple times @@ -1041,7 +1105,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit a ping @@ -1071,7 +1142,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit a ping @@ -1101,7 +1179,14 @@ mod test { let (mut glean, _t) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit a ping @@ -1133,7 +1218,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit a ping @@ -1174,7 +1266,17 @@ mod test { let path2 = format!("/submit/app_id/test-ping/1/{}", doc2); // Enqueue a ping - upload_manager.enqueue_ping(&glean, &doc1, &path1, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: doc1.clone(), + upload_path: path1, + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "test-ping".into(), + }, + ); // Try and get the first request. let req = match upload_manager.get_upload_task(&glean, false) { @@ -1184,7 +1286,17 @@ mod test { assert_eq!(doc1, req.document_id); // Schedule the next one while the first one is "in progress" - upload_manager.enqueue_ping(&glean, &doc2, &path2, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: doc2.clone(), + upload_path: path2, + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "test-ping".into(), + }, + ); // Mark as processed upload_manager.process_ping_upload_response( @@ -1221,7 +1333,14 @@ mod test { glean.set_debug_view_tag("valid-tag"); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit a ping @@ -1248,8 +1367,28 @@ mod test { let path = format!("/submit/app_id/test-ping/1/{}", doc_id); // Try to enqueue a ping with the same doc_id twice - upload_manager.enqueue_ping(&glean, &doc_id, &path, "", None); - upload_manager.enqueue_ping(&glean, &doc_id, &path, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: doc_id.clone(), + upload_path: path.clone(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "test-ping".into(), + }, + ); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: doc_id, + upload_path: path, + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "test-ping".into(), + }, + ); // Get a task once let task = upload_manager.get_upload_task(&glean, false); @@ -1267,7 +1406,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit the ping multiple times @@ -1317,7 +1463,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // Submit the ping multiple times @@ -1331,7 +1484,10 @@ mod test { // The pending pings array is sorted by date in ascending order, // the newest element is the last one. let (_, newest_ping) = &pending_pings.last().unwrap(); - let (newest_ping_id, _, _, _) = &newest_ping; + let PingPayload { + document_id: newest_ping_id, + .. + } = &newest_ping; // Create a new upload manager pointing to the same data_path as the glean instance. let mut upload_manager = PingUploadManager::no_policy(dir.path()); @@ -1385,7 +1541,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); // How many pings we allow at maximum @@ -1406,7 +1569,7 @@ mod test { .iter() .rev() .take(count_quota) - .map(|(_, ping)| ping.0.clone()) + .map(|(_, ping)| ping.document_id.clone()) .collect::<Vec<_>>(); // Create a new upload manager pointing to the same data_path as the glean instance. @@ -1457,7 +1620,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); let expected_number_of_pings = 3; @@ -1477,7 +1647,7 @@ mod test { .iter() .rev() .take(expected_number_of_pings) - .map(|(_, ping)| ping.0.clone()) + .map(|(_, ping)| ping.document_id.clone()) .collect::<Vec<_>>(); // Create a new upload manager pointing to the same data_path as the glean instance. @@ -1531,7 +1701,14 @@ mod test { let (mut glean, dir) = new_glean(None); // Register a ping for testing - let ping_type = PingType::new("test", true, /* send_if_empty */ true, true, vec![]); + let ping_type = PingType::new( + "test", + true, + /* send_if_empty */ true, + true, + true, + vec![], + ); glean.register_ping_type(&ping_type); let expected_number_of_pings = 2; @@ -1551,7 +1728,7 @@ mod test { .iter() .rev() .take(expected_number_of_pings) - .map(|(_, ping)| ping.0.clone()) + .map(|(_, ping)| ping.document_id.clone()) .collect::<Vec<_>>(); // Create a new upload manager pointing to the same data_path as the glean instance. @@ -1622,8 +1799,28 @@ mod test { upload_manager.set_rate_limiter(secs_per_interval, max_pings_per_interval); // Enqueue two pings - upload_manager.enqueue_ping(&glean, &Uuid::new_v4().to_string(), PATH, "", None); - upload_manager.enqueue_ping(&glean, &Uuid::new_v4().to_string(), PATH, "", None); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: Uuid::new_v4().to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }, + ); + upload_manager.enqueue_ping( + &glean, + PingPayload { + document_id: Uuid::new_v4().to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }, + ); // Get the first ping, it should be returned normally. match upload_manager.get_upload_task(&glean, false) { @@ -1679,12 +1876,28 @@ mod test { let upload_manager = PingUploadManager::no_policy(dir.path()); // Enqueue a ping and start processing it - let identifier = &Uuid::new_v4().to_string(); - upload_manager.enqueue_ping(&glean, identifier, PATH, "", None); + let identifier = &Uuid::new_v4(); + let ping = PingPayload { + document_id: identifier.to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }; + upload_manager.enqueue_ping(&glean, ping); assert!(upload_manager.get_upload_task(&glean, false).is_upload()); // Attempt to re-enqueue the same ping - upload_manager.enqueue_ping(&glean, identifier, PATH, "", None); + let ping = PingPayload { + document_id: identifier.to_string(), + upload_path: PATH.into(), + json_body: "".into(), + headers: None, + body_has_info_sections: true, + ping_name: "ping-name".into(), + }; + upload_manager.enqueue_ping(&glean, ping); // No new pings should have been enqueued so the upload task is Done. assert_eq!( @@ -1695,7 +1908,7 @@ mod test { // Process the upload response upload_manager.process_ping_upload_response( &glean, - identifier, + &identifier.to_string(), UploadResult::http_status(200), ); } diff --git a/third_party/rust/glean-core/src/upload/request.rs b/third_party/rust/glean-core/src/upload/request.rs index 0fd5ec5713..b4ac6eba97 100644 --- a/third_party/rust/glean-core/src/upload/request.rs +++ b/third_party/rust/glean-core/src/upload/request.rs @@ -62,6 +62,8 @@ pub struct Builder { body: Option<Vec<u8>>, headers: HeaderMap, body_max_size: usize, + body_has_info_sections: Option<bool>, + ping_name: Option<String>, } impl Builder { @@ -87,6 +89,8 @@ impl Builder { body: None, headers, body_max_size, + body_has_info_sections: None, + ping_name: None, } } @@ -138,6 +142,18 @@ impl Builder { self } + /// Sets whether the request body has {client|ping}_info sections. + pub fn body_has_info_sections(mut self, body_has_info_sections: bool) -> Self { + self.body_has_info_sections = Some(body_has_info_sections); + self + } + + /// Sets the ping's name aka doctype. + pub fn ping_name<S: Into<String>>(mut self, ping_name: S) -> Self { + self.ping_name = Some(ping_name.into()); + self + } + /// Sets a header for this request. pub fn header<S: Into<String>>(mut self, key: S, value: S) -> Self { self.headers.insert(key.into(), value.into()); @@ -174,6 +190,12 @@ impl Builder { .expect("path must be set before attempting to build PingRequest"), body, headers: self.headers, + body_has_info_sections: self.body_has_info_sections.expect( + "body_has_info_sections must be set before attempting to build PingRequest", + ), + ping_name: self + .ping_name + .expect("ping_name must be set before attempting to build PingRequest"), }) } } @@ -192,6 +214,10 @@ pub struct PingRequest { pub body: Vec<u8>, /// A map with all the headers to be sent with the request. pub headers: HeaderMap, + /// Whether the body has {client|ping}_info sections. + pub body_has_info_sections: bool, + /// The ping's name. Likely also somewhere in `path`. + pub ping_name: String, } impl PingRequest { @@ -208,12 +234,7 @@ impl PingRequest { /// Verifies if current request is for a deletion-request ping. pub fn is_deletion_request(&self) -> bool { - // The path format should be `/submit/<app_id>/<ping_name>/<schema_version/<doc_id>` - self.path - .split('/') - .nth(3) - .map(|url| url == "deletion-request") - .unwrap_or(false) + self.ping_name == "deletion-request" } /// Decompresses and pretty-format the ping payload @@ -257,11 +278,15 @@ mod test { .document_id("woop") .path("/random/path/doesnt/matter") .body("{}") + .body_has_info_sections(false) + .ping_name("whatevs") .build() .unwrap(); assert_eq!(request.document_id, "woop"); assert_eq!(request.path, "/random/path/doesnt/matter"); + assert!(!request.body_has_info_sections); + assert_eq!(request.ping_name, "whatevs"); // Make sure all the expected headers were added. assert!(request.headers.contains_key("X-Telemetry-Agent")); |