/// Sets the library's domain resolver implementation. /// /// If the `embedded-domain-resolver` feature is disabled and the library is /// used without this having been set, panics may occur! /// /// Will return the resolver if it has already been previously set. #[cfg(not(feature = "embedded-domain-resolver"))] pubfn set_domain_resolver(
resolver: Box<dyn ResolvesDomain>,
) -> Result<(), Box<dyn ResolvesDomain>> {
DOMAIN_RESOLVER.set(resolver)
}
/// Default `addr`-based domain resolution implementation used when the /// `embedded-domain-resolver` feature is enabled. #[cfg(feature = "embedded-domain-resolver")] struct DefaultResolver;
#[cfg(feature = "embedded-domain-resolver")] impl ResolvesDomain for DefaultResolver { fn get_host_domain(&self, host: &str) -> (usize, usize) { use addr::parser::DomainName; use addr::psl::List;
if host.is_empty() {
(0, 0)
} else { match List.parse_domain_name(host) {
Err(_e) => (0, host.len()),
Ok(domain) => { let host_len = host.len(); let domain_len = domain.root().unwrap_or_else(|| domain.suffix()).len();
(host_len - domain_len, host_len)
}
}
}
}
}
/// Required trait for any domain resolution implementation used with this /// crate. pubtrait ResolvesDomain: Send + Sync { /// Return the start and end indices of the domain (eTLD+1) of the given hostname. /// /// If there isn't a valid domain, `(0, host.len())` should be returned. /// /// ``` /// # use adblock::url_parser::ResolvesDomain; /// # /// I'd use DefaultResolver here, but I can't use private structs in doctests. /// # /// Enjoy this mock implementation instead :( /// # struct Resolver; /// # impl ResolvesDomain for Resolver { /// # fn get_host_domain(&self, host: &str) -> (usize, usize) { /// # match host { /// # "api.m.example.com" => (6, 17), /// # "a.b.co.uk" => (2, 9), /// # _ => unreachable!() /// # } /// # } /// # } /// # let resolver = Resolver; /// let host = "api.m.example.com"; /// let (start, end) = resolver.get_host_domain(host); /// assert_eq!(&host[start..end], "example.com"); /// /// let host = "a.b.co.uk"; /// let (start, end) = resolver.get_host_domain(host); /// assert_eq!(&host[start..end], "b.co.uk"); /// ``` fn get_host_domain(&self, host: &str) -> (usize, usize);
}
/// Return the start and end indices of the domain of the given hostname. pub(crate) fn get_host_domain(host: &str) -> (usize, usize) { #[cfg(not(feature = "embedded-domain-resolver"))] let domain_resolver = DOMAIN_RESOLVER.get().expect("An external domain resolver must be set when the `embedded-domain-resolver` feature is disabled."); #[cfg(feature = "embedded-domain-resolver")] let domain_resolver = DefaultResolver;
domain_resolver.get_host_domain(host)
}
/// Return the string representation of the host (domain or IP address) for /// this URL, if any together with the URL. /// /// As part of hostname parsing, punycode decoding is used to convert URLs with /// UTF characters to plain ASCII ones. Serialisation then contains this /// decoded URL that is used for further matching. pubfn parse_url(url: &str) -> Option<RequestUrl> { let parsed = parser::Hostname::parse(url).ok();
parsed.and_then(|h| match h.host_str() {
Some(_host) => Some(RequestUrl {
url: h.url_str().to_owned(),
schema_end: h.scheme_end,
hostname_pos: (h.host_start, h.host_end),
domain: get_host_domain(&h.url_str()[h.host_start..h.host_end]),
}),
_ => None,
})
}
#[cfg(all(test, feature = "embedded-domain-resolver"))] mod embedded_domain_resolver_tests { usesuper::*;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.