Skip to main content
The whatwaf library uses structured types for configuration and results. This page documents the ScanConfig and ProbeResult types.

ScanConfig

The ScanConfig struct controls scan behavior:
pub struct ScanConfig {
    pub timeout: u64,
    pub follow_redirects: bool,
    pub proxy: Option<String>,
}

Fields

timeout
u64
required
Request timeout in seconds. Each probe request will wait up to this duration before timing out.Example: 10 for a 10-second timeout
follow_redirects
bool
required
Whether to follow HTTP redirects (3xx status codes).
  • true - Follow redirects automatically
  • false - Stop at the first redirect response
Setting this to false can help detect WAFs that redirect suspicious requests.
proxy
Option<String>
required
Optional HTTP/HTTPS proxy URL.
  • None - No proxy, direct connection
  • Some(url) - Route requests through the specified proxy
Format: http://host:port or https://host:portExample: Some("http://127.0.0.1:8080".to_string())

Configuration examples

Default configuration

use whatwaf::ScanConfig;

let config = ScanConfig {
    timeout: 10,
    follow_redirects: true,
    proxy: None,
};

No redirects, longer timeout

use whatwaf::ScanConfig;

let config = ScanConfig {
    timeout: 30,
    follow_redirects: false,
    proxy: None,
};

Using a proxy

use whatwaf::ScanConfig;

let config = ScanConfig {
    timeout: 15,
    follow_redirects: true,
    proxy: Some("http://localhost:8080".to_string()),
};

Burp Suite proxy

use whatwaf::ScanConfig;

let config = ScanConfig {
    timeout: 20,
    follow_redirects: false,
    proxy: Some("http://127.0.0.1:8080".to_string()),
};

ProbeResult

The ProbeResult struct contains the results of a single probe:
#[derive(Clone, Debug)]
pub struct ProbeResult {
    pub probe_name: String,
    pub url: String,
    pub status: u16,
    pub detected_wafs: Option<Vec<String>>,
}

Fields

probe_name
String
required
Name of the probe that was executed.Possible values:
  • "plain request" - Baseline request
  • "xss" - Cross-site scripting probe
  • "sql injection" - SQL injection probe
  • "lfi" - Local file inclusion probe
url
String
required
The actual URL that was requested, including any probe parameters.Example: "https://example.com?q=<script>alert(1)</script>"
status
u16
required
HTTP status code returned by the server.Example: 200, 403, 418
detected_wafs
Option<Vec<String>>
required
List of detected WAF names, or None if no WAFs were detected.
  • Some(vec![...]) - One or more WAFs detected
  • Some(vec![]) - No WAFs detected (empty list)
  • None - No detection attempted or no detectors matched
Example: Some(vec!["Cloudflare".to_string(), "Akamai Kona".to_string()])

Using ProbeResult

Checking for detections

use whatwaf::{scan_url, ScanConfig};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ScanConfig {
        timeout: 10,
        follow_redirects: true,
        proxy: None,
    };

    let result = scan_url("https://example.com", config, None)?;

    if let Some(probe_result) = result {
        println!("Probe: {}", probe_result.probe_name);
        println!("Status: {}", probe_result.status);
        
        match &probe_result.detected_wafs {
            Some(wafs) if !wafs.is_empty() => {
                println!("Detected WAFs:");
                for waf in wafs {
                    println!("  - {}", waf);
                }
            }
            _ => println!("No WAFs detected"),
        }
    }

    Ok(())
}

Processing all probes with callback

use whatwaf::{scan_url, ScanConfig, ProbeResult};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ScanConfig {
        timeout: 10,
        follow_redirects: true,
        proxy: None,
    };

    let mut all_detections: Vec<String> = Vec::new();

    scan_url(
        "https://example.com",
        config,
        Some(|probe: &ProbeResult| {
            if let Some(wafs) = &probe.detected_wafs {
                for waf in wafs {
                    if !all_detections.contains(waf) {
                        all_detections.push(waf.clone());
                    }
                }
            }
            true // Continue with all probes
        }),
    )?;

    println!("All detected WAFs: {:?}", all_detections);

    Ok(())
}

Early termination on detection

use whatwaf::{scan_url, ScanConfig, ProbeResult};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ScanConfig {
        timeout: 10,
        follow_redirects: true,
        proxy: None,
    };

    let result = scan_url(
        "https://example.com",
        config,
        Some(|probe: &ProbeResult| {
            // Stop as soon as we detect any WAF
            if let Some(wafs) = &probe.detected_wafs {
                if !wafs.is_empty() {
                    println!("Found WAF: {:?}", wafs);
                    return false; // Stop scanning
                }
            }
            true // Continue
        }),
    )?;

    if let Some(last) = result {
        println!("Stopped at probe: {}", last.probe_name);
    }

    Ok(())
}

Build docs developers (and LLMs) love