use super::{ScanContext, ScanPhase};
use crate::http::tester::HeaderAnalyzer;
use crate::{Args, Result};
use async_trait::async_trait;
pub struct HttpHeadersPhase;
impl HttpHeadersPhase {
pub fn new() -> Self {
Self
}
fn configure_analyzer(&self, context: &ScanContext) -> HeaderAnalyzer {
let target = context.target();
let mut analyzer = if !context.args.http.custom_headers.is_empty() {
let custom_headers: Vec<(String, String)> = context
.args
.http
.custom_headers
.iter()
.filter_map(|h| {
let parts: Vec<&str> = h.splitn(2, ':').collect();
if parts.len() == 2 {
Some((parts[0].trim().to_string(), parts[1].trim().to_string()))
} else {
eprintln!(
"Warning: Invalid header format '{}', expected 'Name: Value'",
h
);
None
}
})
.collect();
HeaderAnalyzer::with_custom_headers(target, custom_headers)
} else {
HeaderAnalyzer::new(target)
};
if context.args.http.sneaky {
use crate::utils::sneaky::SneakyConfig;
let sneaky_config = SneakyConfig::new(true);
analyzer = analyzer.with_user_agent(sneaky_config.user_agent().to_string());
}
analyzer
}
}
impl Default for HttpHeadersPhase {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl ScanPhase for HttpHeadersPhase {
fn name(&self) -> &'static str {
"Analyzing HTTP Security Headers"
}
fn should_run(&self, args: &Args) -> bool {
args.scan.headers || args.scan.all
}
async fn execute(&self, context: &mut ScanContext) -> Result<()> {
let analyzer = self.configure_analyzer(context);
let header_results = analyzer.analyze().await?;
context.results.http_mut().http_headers = Some(header_results);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn test_http_headers_phase_should_run() {
let phase = HttpHeadersPhase::new();
let mut args = Args::default();
args.scan.headers = true;
assert!(phase.should_run(&args));
let mut args = Args::default();
args.scan.all = true;
assert!(phase.should_run(&args));
let mut args = Args::default();
args.target = Some("example.com".to_string());
assert!(!phase.should_run(&args));
let args = Args::default();
assert!(!phase.should_run(&args));
}
#[test]
fn test_http_headers_phase_name() {
let phase = HttpHeadersPhase::new();
assert_eq!(phase.name(), "Analyzing HTTP Security Headers");
}
}