proxyfor 0.5.0

A powerful and flexible proxy CLI for capturing and inspecting HTTP(S) and WS(S) traffic
Documentation
use anyhow::{Context, Result};
use fancy_regex::Regex;

pub fn parse_title_filters(filters: &[String]) -> Result<Vec<TitleFilter>> {
    let mut output = vec![];
    for filter in filters {
        if let Some(re) = filter.strip_prefix('/').and_then(|v| v.strip_suffix('/')) {
            let regex = Regex::new(&re.to_lowercase())
                .with_context(|| format!("Invalid filter regex: {filter}"))?;
            output.push(TitleFilter::Regex(regex));
        } else {
            output.push(TitleFilter::Plain(filter.to_lowercase()));
        }
    }
    Ok(output)
}

pub fn is_match_title(filters: &[TitleFilter], title: &str) -> bool {
    if filters.is_empty() {
        true
    } else {
        let title = title.to_lowercase();
        filters.iter().any(|v| v.is_match(&title))
    }
}

pub fn is_match_type(filters: &[String], content_type: &str) -> bool {
    if filters.is_empty() {
        true
    } else {
        let content_type = content_type.to_lowercase();
        filters.iter().any(|v| content_type.starts_with(v))
    }
}

#[derive(Debug)]
pub enum TitleFilter {
    Regex(Regex),
    Plain(String),
}

impl TitleFilter {
    pub fn is_match(&self, value: &str) -> bool {
        match self {
            TitleFilter::Regex(v) => v.is_match(value).unwrap_or_default(),
            TitleFilter::Plain(v) => value.contains(v),
        }
    }
}

#[test]
fn test_filters() {
    let filters = parse_title_filters(&[
        "postman-echo.com".to_string(),
        "/^(GET|POST) https:\\/\\/httpbin.org/".to_string(),
    ])
    .unwrap();
    assert!(is_match_title(&filters, "GET https://postman-echo.com/get"));
    assert!(is_match_title(&filters, "GET https://httpbin.org"));
    assert!(is_match_title(&filters, "POST https://httpbin.org"));
    assert!(!is_match_title(&filters, "PUT https://httpbin.org"));
}

#[test]
fn test_is_asset() {
    let filters = vec!["application/json".to_string()];
    assert!(is_match_type(&filters, "application/json"));
    let filters = vec!["application/".to_string()];
    assert!(is_match_type(&filters, "application/json"));
}