use crw_core::config::SearchConfig;
use tracing::Level;
pub fn sanitize_url_origin(raw: &str) -> String {
match url::Url::parse(raw) {
Ok(u) => match (u.host_str(), u.port()) {
(Some(host), Some(port)) => format!("{}://{host}:{port}", u.scheme()),
(Some(host), None) => format!("{}://{host}", u.scheme()),
(None, _) => "<redacted-url>".to_string(),
},
Err(_) => "<redacted-url>".to_string(),
}
}
pub fn search_startup_status(cfg: &SearchConfig) -> (Level, String) {
if !cfg.enabled {
(
Level::INFO,
"search: disabled ([search].enabled = false)".to_string(),
)
} else if let Some(url) = &cfg.searxng_url {
(
Level::INFO,
format!("search: enabled (searxng={})", sanitize_url_origin(url)),
)
} else {
(
Level::WARN,
"search: enabled but no [search].searxng_url — /v1/search will return 503".to_string(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanitize_strips_userinfo_path_query_fragment() {
assert_eq!(
sanitize_url_origin("https://user:pass@host:9000/searxng/tok123?q=x#frag"),
"https://host:9000"
);
assert_eq!(
sanitize_url_origin("http://searxng:8080"),
"http://searxng:8080"
);
assert_eq!(
sanitize_url_origin("http://searxng:8080/"),
"http://searxng:8080"
);
assert_eq!(
sanitize_url_origin("https://example.com"),
"https://example.com"
);
}
#[test]
fn sanitize_redacts_unparseable() {
assert_eq!(sanitize_url_origin("not a url"), "<redacted-url>");
}
fn cfg(enabled: bool, url: Option<&str>) -> SearchConfig {
let toml = match url {
Some(u) => format!("enabled = {enabled}\nsearxng_url = \"{u}\"\n"),
None => format!("enabled = {enabled}\n"),
};
toml::from_str(&toml).expect("valid SearchConfig")
}
#[test]
fn startup_status_enabled_with_url() {
let (level, msg) = search_startup_status(&cfg(true, Some("http://searxng:8080")));
assert_eq!(level, Level::INFO);
assert!(
msg.contains("enabled (searxng=http://searxng:8080)"),
"{msg}"
);
}
#[test]
fn startup_status_enabled_no_url_warns() {
let (level, msg) = search_startup_status(&cfg(true, None));
assert_eq!(level, Level::WARN);
assert!(msg.contains("no [search].searxng_url"), "{msg}");
}
#[test]
fn startup_status_disabled() {
let (level, msg) = search_startup_status(&cfg(false, Some("http://searxng:8080")));
assert_eq!(level, Level::INFO);
assert!(msg.contains("disabled"), "{msg}");
}
#[test]
fn startup_status_never_leaks_credentials() {
let (_, msg) = search_startup_status(&cfg(true, Some("https://u:secret@host:8080/tok")));
assert!(!msg.contains("secret"), "{msg}");
assert!(!msg.contains("tok"), "{msg}");
assert!(msg.contains("https://host:8080"), "{msg}");
}
}