use std::collections::HashSet;
use std::sync::OnceLock;
static PREAPPROVED_DOMAINS: OnceLock<HashSet<&'static str>> = OnceLock::new();
fn preapproved_domains() -> &'static HashSet<&'static str> {
PREAPPROVED_DOMAINS.get_or_init(|| {
HashSet::from([
"doc.rust-lang.org",
"docs.rs",
"crates.io",
"rust-lang.org",
"www.typescriptlang.org",
"typescriptlang.org",
"developer.mozilla.org",
"developer.mozilla.org",
"docs.python.org",
"peps.python.org",
"packaging.python.org",
"wiki.python.org",
"pkg.go.dev",
"go.dev",
"nodejs.org",
"react.dev",
"vuejs.org",
"angular.io",
"angular.dev",
"nextjs.org",
"tailwindcss.com",
"svelte.dev",
"nuxt.com",
"getbootstrap.com",
"bulma.io",
"swagger.io",
"www.openapis.org",
"docs.aws.amazon.com",
"cloud.google.com",
"learn.microsoft.com",
"docs.microsoft.com",
"developer.apple.com",
"firebase.google.com",
"www.postgresql.org",
"dev.mysql.com",
"redis.io",
"mongodb.com",
"sqlite.org",
"docs.github.com",
"docs.gitlab.com",
"www.jenkins.io",
"github.com",
"stackoverflow.com",
"wikipedia.org",
"en.wikipedia.org",
"dart.dev",
"flutter.dev",
"kotlinlang.org",
"www.ruby-doc.org",
"ruby-doc.org",
"docs.oracle.com",
"hc.apache.org",
"nginx.org",
])
})
}
pub fn is_preapproved_url(url: &url::Url) -> bool {
let Some(host) = url.host_str() else {
return false;
};
let host_lower = host.to_lowercase();
let domains = preapproved_domains();
if domains.contains(host_lower.as_str()) {
return true;
}
for domain in domains.iter() {
if host_lower.ends_with(&format!(".{domain}")) {
return true;
}
}
false
}
pub const PREAPPROVED_MAX_CHARS: usize = 100_000;
pub const PREAPPROVED_QUOTE_LIMIT: usize = 5_000;
pub const NON_PREAPPROVED_QUOTE_LIMIT: usize = 500;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rust_docs_is_preapproved() {
let url = url::Url::parse("https://doc.rust-lang.org/std/").unwrap();
assert!(is_preapproved_url(&url));
}
#[test]
fn docs_rs_is_preapproved() {
let url = url::Url::parse("https://docs.rs/serde/1.0").unwrap();
assert!(is_preapproved_url(&url));
}
#[test]
fn mdn_is_preapproved() {
let url = url::Url::parse("https://developer.mozilla.org/en-US/docs/Web").unwrap();
assert!(is_preapproved_url(&url));
}
#[test]
fn random_site_not_preapproved() {
let url = url::Url::parse("https://example.com/").unwrap();
assert!(!is_preapproved_url(&url));
}
#[test]
fn subdomain_of_preapproved_is_matched() {
let url = url::Url::parse("https://docs.python.org/3/").unwrap();
assert!(is_preapproved_url(&url));
}
#[test]
fn preapproved_max_chars_is_100k() {
assert_eq!(PREAPPROVED_MAX_CHARS, 100_000);
}
}