Skip to content

Commit

Permalink
added timestamp field to responses
Browse files Browse the repository at this point in the history
  • Loading branch information
epi052 committed Mar 30, 2024
1 parent f3d6d18 commit 4f53f4f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
20 changes: 19 additions & 1 deletion src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
event_handlers::{Command, Handles},
traits::FeroxSerialize,
url::FeroxUrl,
utils::{self, fmt_err, parse_url_with_raw_path, status_colorizer},
utils::{self, fmt_err, parse_url_with_raw_path, status_colorizer, timestamp},
CommandSender,
};

Expand Down Expand Up @@ -63,6 +63,9 @@ pub struct FeroxResponse {

/// Url's file extension, if one exists
pub(crate) extension: Option<String>,

/// Timestamp of when this response was received
timestamp: f64,
}

/// implement Default trait for FeroxResponse
Expand All @@ -82,6 +85,7 @@ impl Default for FeroxResponse {
wildcard: false,
output_level: Default::default(),
extension: None,
timestamp: timestamp(),
}
}
}
Expand Down Expand Up @@ -138,6 +142,11 @@ impl FeroxResponse {
self.content_length
}

/// Get the timestamp of this response
pub fn timestamp(&self) -> f64 {
self.timestamp
}

/// Set `FeroxResponse`'s `url` attribute, has no affect if an error occurs
pub fn set_url(&mut self, url: &str) {
match parse_url_with_raw_path(url) {
Expand Down Expand Up @@ -216,6 +225,7 @@ impl FeroxResponse {
let status = response.status();
let headers = response.headers().clone();
let content_length = response.content_length().unwrap_or(0);
let timestamp = timestamp();

// .text() consumes the response, must be called last
let text = response
Expand Down Expand Up @@ -248,6 +258,7 @@ impl FeroxResponse {
output_level,
wildcard: false,
extension: None,
timestamp,
}
}

Expand Down Expand Up @@ -574,6 +585,7 @@ impl Serialize for FeroxResponse {
"extension",
self.extension.as_ref().unwrap_or(&String::new()),
)?;
state.serialize_field("timestamp", &self.timestamp)?;

state.end()
}
Expand All @@ -599,6 +611,7 @@ impl<'de> Deserialize<'de> for FeroxResponse {
line_count: 0,
word_count: 0,
extension: None,
timestamp: timestamp(),
};

let map: HashMap<String, Value> = HashMap::deserialize(deserializer)?;
Expand Down Expand Up @@ -672,6 +685,11 @@ impl<'de> Deserialize<'de> for FeroxResponse {
response.extension = Some(result.to_string());
}
}
"timestamp" => {
if let Some(result) = value.as_f64() {
response.timestamp = result;
}
}
_ => {}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/scan_manager/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ fn ferox_scans_serialize() {
#[test]
/// given a FeroxResponses, test that it serializes into the proper JSON entry
fn ferox_responses_serialize() {
let json_response = r#"{"type":"response","url":"https://nerdcore.com/css","original_url":"https://nerdcore.com","path":"/css","wildcard":true,"status":301,"method":"GET","content_length":173,"line_count":10,"word_count":16,"headers":{"server":"nginx/1.16.1"},"extension":""}"#;
let json_response = r#"{"type":"response","url":"https://nerdcore.com/css","original_url":"https://nerdcore.com","path":"/css","wildcard":true,"status":301,"method":"GET","content_length":173,"line_count":10,"word_count":16,"headers":{"server":"nginx/1.16.1"},"extension":"","timestamp":1711796681.3455093}"#;
let response: FeroxResponse = serde_json::from_str(json_response).unwrap();

let responses = FeroxResponses::default();
Expand All @@ -332,7 +332,7 @@ fn ferox_responses_serialize() {
/// given a FeroxResponse, test that it serializes into the proper JSON entry
fn ferox_response_serialize_and_deserialize() {
// deserialize
let json_response = r#"{"type":"response","url":"https://nerdcore.com/css","original_url":"https://nerdcore.com","path":"/css","wildcard":true,"status":301,"method":"GET","content_length":173,"line_count":10,"word_count":16,"headers":{"server":"nginx/1.16.1"},"extension":""}"#;
let json_response = r#"{"type":"response","url":"https://nerdcore.com/css","original_url":"https://nerdcore.com","path":"/css","wildcard":true,"status":301,"method":"GET","content_length":173,"line_count":10,"word_count":16,"headers":{"server":"nginx/1.16.1"},"extension":"","timestamp":1711796681.3455093}"#;
let response: FeroxResponse = serde_json::from_str(json_response).unwrap();

assert_eq!(response.url().as_str(), "https://nerdcore.com/css");
Expand All @@ -343,6 +343,7 @@ fn ferox_response_serialize_and_deserialize() {
assert_eq!(response.line_count(), 10);
assert_eq!(response.word_count(), 16);
assert_eq!(response.headers().get("server").unwrap(), "nginx/1.16.1");
assert_eq!(response.timestamp(), 1711796681.3455093);

// serialize, however, this can fail when headers are out of order
let new_json = serde_json::to_string(&response).unwrap();
Expand Down
14 changes: 14 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ pub fn fmt_err(msg: &str) -> String {
format!("{}: {}", status_colorizer("ERROR"), msg)
}

/// simple wrapper to get the current system time as
/// time elapsed from unix epoch
pub fn timestamp() -> f64 {
let since_the_epoch = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_else(|_| Duration::from_secs(0));

let secs = since_the_epoch.as_secs() as f64;
let nanos = since_the_epoch.subsec_nanos() as f64;

// Convert nanoseconds to fractional seconds and add to secs
secs + (nanos / 1_000_000_000.0)
}

/// given a FeroxResponse, send a TryRecursion command
///
/// moved to utils to allow for calls from extractor and scanner
Expand Down

0 comments on commit 4f53f4f

Please sign in to comment.