mirror of
https://github.com/epi052/feroxbuster.git
synced 2026-05-26 07:41:12 -03:00
moved FeroxMessage from lib.rs
This commit is contained in:
121
src/ferox_message.rs
Normal file
121
src/ferox_message.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
use anyhow::Context;
|
||||
use console::{style, Color};
|
||||
|
||||
use crate::traits::FeroxSerialize;
|
||||
use crate::utils::fmt_err;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
/// Representation of a log entry, can be represented as a human readable string or JSON
|
||||
pub struct FeroxMessage {
|
||||
#[serde(rename = "type")]
|
||||
/// Name of this type of struct, used for serialization, i.e. `{"type":"log"}`
|
||||
pub(crate) kind: String,
|
||||
|
||||
/// The log message
|
||||
pub(crate) message: String,
|
||||
|
||||
/// The log level
|
||||
pub(crate) level: String,
|
||||
|
||||
/// The number of seconds elapsed since the scan started
|
||||
pub(crate) time_offset: f32,
|
||||
|
||||
/// The module from which log::* was called
|
||||
pub(crate) module: String,
|
||||
}
|
||||
|
||||
/// Implementation of FeroxMessage
|
||||
impl FeroxSerialize for FeroxMessage {
|
||||
/// Create a string representation of the log message
|
||||
///
|
||||
/// ex: 301 10l 16w 173c https://localhost/api
|
||||
fn as_str(&self) -> String {
|
||||
let (level_name, level_color) = match self.level.as_str() {
|
||||
"ERROR" => ("ERR", Color::Red),
|
||||
"WARN" => ("WRN", Color::Red),
|
||||
"INFO" => ("INF", Color::Cyan),
|
||||
"DEBUG" => ("DBG", Color::Yellow),
|
||||
"TRACE" => ("TRC", Color::Magenta),
|
||||
"WILDCARD" => ("WLD", Color::Cyan),
|
||||
_ => ("UNK", Color::White),
|
||||
};
|
||||
|
||||
format!(
|
||||
"{} {:10.03} {} {}\n",
|
||||
style(level_name).bg(level_color).black(),
|
||||
style(self.time_offset).dim(),
|
||||
self.module,
|
||||
style(&self.message).dim(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create an NDJSON representation of the log message
|
||||
///
|
||||
/// (expanded for clarity)
|
||||
/// ex:
|
||||
/// {
|
||||
/// "type": "log",
|
||||
/// "message": "Sent https://localhost/api to file handler",
|
||||
/// "level": "DEBUG",
|
||||
/// "time_offset": 0.86333454,
|
||||
/// "module": "feroxbuster::reporter"
|
||||
/// }\n
|
||||
fn as_json(&self) -> anyhow::Result<String> {
|
||||
let mut json = serde_json::to_string(&self).with_context(|| {
|
||||
fmt_err(&format!(
|
||||
"Could not convert {}:{} to JSON",
|
||||
self.level, self.message
|
||||
))
|
||||
})?;
|
||||
json.push('\n');
|
||||
Ok(json)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
/// test as_str method of FeroxMessage
|
||||
fn ferox_message_as_str_returns_string_with_newline() {
|
||||
let message = FeroxMessage {
|
||||
message: "message".to_string(),
|
||||
module: "utils".to_string(),
|
||||
time_offset: 1.0,
|
||||
level: "INFO".to_string(),
|
||||
kind: "log".to_string(),
|
||||
};
|
||||
let message_str = message.as_str();
|
||||
|
||||
assert!(message_str.contains("INF"));
|
||||
assert!(message_str.contains("1.000"));
|
||||
assert!(message_str.contains("utils"));
|
||||
assert!(message_str.contains("message"));
|
||||
assert!(message_str.ends_with('\n'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// test as_json method of FeroxMessage
|
||||
fn ferox_message_as_json_returns_json_representation_of_ferox_message_with_newline() {
|
||||
let message = FeroxMessage {
|
||||
message: "message".to_string(),
|
||||
module: "utils".to_string(),
|
||||
time_offset: 1.0,
|
||||
level: "INFO".to_string(),
|
||||
kind: "log".to_string(),
|
||||
};
|
||||
|
||||
let message_str = message.as_json().unwrap();
|
||||
|
||||
let error_margin = f32::EPSILON;
|
||||
|
||||
let json: FeroxMessage = serde_json::from_str(&message_str).unwrap();
|
||||
assert_eq!(json.module, message.module);
|
||||
assert_eq!(json.message, message.message);
|
||||
assert!((json.time_offset - message.time_offset).abs() < error_margin);
|
||||
assert_eq!(json.level, message.level);
|
||||
assert_eq!(json.kind, message.kind);
|
||||
}
|
||||
}
|
||||
119
src/lib.rs
119
src/lib.rs
@@ -1,13 +1,13 @@
|
||||
use anyhow::{Context, Result};
|
||||
use console::{style, Color};
|
||||
use anyhow::Result;
|
||||
use reqwest::StatusCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::{
|
||||
sync::mpsc::{UnboundedReceiver, UnboundedSender},
|
||||
task::JoinHandle,
|
||||
};
|
||||
|
||||
use crate::{event_handlers::Command, traits::FeroxSerialize, utils::fmt_err};
|
||||
// todo should FeroxSerialize be imported from traits all the places its used? currently most do crate::FeroxSerialize
|
||||
// the other option would be to expose all the Ferox stuff here and make them internally private
|
||||
use crate::{event_handlers::Command, traits::FeroxSerialize};
|
||||
|
||||
pub mod banner;
|
||||
pub mod config;
|
||||
@@ -27,6 +27,7 @@ mod extractor;
|
||||
mod macros;
|
||||
mod ferox_url;
|
||||
mod ferox_response;
|
||||
mod ferox_message;
|
||||
|
||||
/// Alias for tokio::sync::mpsc::UnboundedSender<Command>
|
||||
pub(crate) type CommandSender = UnboundedSender<Command>;
|
||||
@@ -88,74 +89,6 @@ pub const DEFAULT_STATUS_CODES: [StatusCode; 9] = [
|
||||
/// Expected location is in the same directory as the feroxbuster binary.
|
||||
pub const DEFAULT_CONFIG_NAME: &str = "ferox-config.toml";
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
/// Representation of a log entry, can be represented as a human readable string or JSON
|
||||
pub struct FeroxMessage {
|
||||
#[serde(rename = "type")]
|
||||
/// Name of this type of struct, used for serialization, i.e. `{"type":"log"}`
|
||||
kind: String,
|
||||
|
||||
/// The log message
|
||||
pub message: String,
|
||||
|
||||
/// The log level
|
||||
pub level: String,
|
||||
|
||||
/// The number of seconds elapsed since the scan started
|
||||
pub time_offset: f32,
|
||||
|
||||
/// The module from which log::* was called
|
||||
pub module: String,
|
||||
}
|
||||
|
||||
/// Implementation of FeroxMessage
|
||||
impl FeroxSerialize for FeroxMessage {
|
||||
/// Create a string representation of the log message
|
||||
///
|
||||
/// ex: 301 10l 16w 173c https://localhost/api
|
||||
fn as_str(&self) -> String {
|
||||
let (level_name, level_color) = match self.level.as_str() {
|
||||
"ERROR" => ("ERR", Color::Red),
|
||||
"WARN" => ("WRN", Color::Red),
|
||||
"INFO" => ("INF", Color::Cyan),
|
||||
"DEBUG" => ("DBG", Color::Yellow),
|
||||
"TRACE" => ("TRC", Color::Magenta),
|
||||
"WILDCARD" => ("WLD", Color::Cyan),
|
||||
_ => ("UNK", Color::White),
|
||||
};
|
||||
|
||||
format!(
|
||||
"{} {:10.03} {} {}\n",
|
||||
style(level_name).bg(level_color).black(),
|
||||
style(self.time_offset).dim(),
|
||||
self.module,
|
||||
style(&self.message).dim(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create an NDJSON representation of the log message
|
||||
///
|
||||
/// (expanded for clarity)
|
||||
/// ex:
|
||||
/// {
|
||||
/// "type": "log",
|
||||
/// "message": "Sent https://localhost/api to file handler",
|
||||
/// "level": "DEBUG",
|
||||
/// "time_offset": 0.86333454,
|
||||
/// "module": "feroxbuster::reporter"
|
||||
/// }\n
|
||||
fn as_json(&self) -> Result<String> {
|
||||
let mut json = serde_json::to_string(&self).with_context(|| {
|
||||
fmt_err(&format!(
|
||||
"Could not convert {}:{} to JSON",
|
||||
self.level, self.message
|
||||
))
|
||||
})?;
|
||||
json.push('\n');
|
||||
Ok(json)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -180,46 +113,4 @@ mod tests {
|
||||
fn default_version() {
|
||||
assert_eq!(VERSION, env!("CARGO_PKG_VERSION"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// test as_str method of FeroxMessage
|
||||
fn ferox_message_as_str_returns_string_with_newline() {
|
||||
let message = FeroxMessage {
|
||||
message: "message".to_string(),
|
||||
module: "utils".to_string(),
|
||||
time_offset: 1.0,
|
||||
level: "INFO".to_string(),
|
||||
kind: "log".to_string(),
|
||||
};
|
||||
let message_str = message.as_str();
|
||||
|
||||
assert!(message_str.contains("INF"));
|
||||
assert!(message_str.contains("1.000"));
|
||||
assert!(message_str.contains("utils"));
|
||||
assert!(message_str.contains("message"));
|
||||
assert!(message_str.ends_with('\n'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// test as_json method of FeroxMessage
|
||||
fn ferox_message_as_json_returns_json_representation_of_ferox_message_with_newline() {
|
||||
let message = FeroxMessage {
|
||||
message: "message".to_string(),
|
||||
module: "utils".to_string(),
|
||||
time_offset: 1.0,
|
||||
level: "INFO".to_string(),
|
||||
kind: "log".to_string(),
|
||||
};
|
||||
|
||||
let message_str = message.as_json().unwrap();
|
||||
|
||||
let error_margin = f32::EPSILON;
|
||||
|
||||
let json: FeroxMessage = serde_json::from_str(&message_str).unwrap();
|
||||
assert_eq!(json.module, message.module);
|
||||
assert_eq!(json.message, message.message);
|
||||
assert!((json.time_offset - message.time_offset).abs() < error_margin);
|
||||
assert_eq!(json.level, message.level);
|
||||
assert_eq!(json.kind, message.kind);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use std::env;
|
||||
use std::fs::OpenOptions;
|
||||
use std::time::Instant;
|
||||
|
||||
use env_logger::Builder;
|
||||
|
||||
use crate::utils::write_to;
|
||||
use crate::{
|
||||
config::{Configuration, PROGRESS_PRINTER},
|
||||
utils::fmt_err,
|
||||
FeroxMessage, FeroxSerialize,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use std::io::BufWriter;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Instant;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use env_logger::Builder;
|
||||
|
||||
use crate::{
|
||||
config::{Configuration, PROGRESS_PRINTER},
|
||||
ferox_message::FeroxMessage,
|
||||
utils::fmt_err,
|
||||
utils::write_to,
|
||||
FeroxSerialize,
|
||||
};
|
||||
|
||||
/// Create a customized instance of
|
||||
/// [env_logger::Logger](https://docs.rs/env_logger/latest/env_logger/struct.Logger.html)
|
||||
|
||||
Reference in New Issue
Block a user