Files
servo/components/net/hosts.rs
Jan Varga f908312750 net: Expose replace_host_table via test_util (#41454)
Expose `replace_host_table` via test_util so it can be reused by other
crates, notably libservo tests.
    
This allows tests to map arbitrary host names to localhost, so loading
of
arbitrary sites can be done via the lightweight http server (without
reaching
the external network).
    
Arbitrary sites are needed for upcoming `SiteDataManager` site grouping
by
domain.

Testing: A new integration test has been added

Signed-off-by: Jan Varga <jvarga@igalia.com>
2025-12-22 11:57:53 +00:00

64 lines
1.9 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::borrow::Cow;
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{BufReader, Read};
use std::net::{IpAddr, Ipv4Addr};
use std::sync::LazyLock;
use parking_lot::Mutex;
static HOST_TABLE: LazyLock<Mutex<Option<HashMap<String, IpAddr>>>> =
LazyLock::new(|| Mutex::new(create_host_table()));
fn create_host_table() -> Option<HashMap<String, IpAddr>> {
let path = env::var_os("HOST_FILE")?;
let file = File::open(path).ok()?;
let mut reader = BufReader::new(file);
let mut lines = String::new();
reader.read_to_string(&mut lines).ok()?;
Some(parse_hostsfile(&lines))
}
#[cfg_attr(not(feature = "test-util"), expect(dead_code))]
pub fn replace_host_table(table: HashMap<String, IpAddr>) {
*HOST_TABLE.lock() = Some(table);
}
pub fn parse_hostsfile(hostsfile_content: &str) -> HashMap<String, IpAddr> {
hostsfile_content
.lines()
.filter_map(|line| {
let mut iter = line.split('#').next().unwrap().split_whitespace();
Some((iter.next()?.parse().ok()?, iter))
})
.flat_map(|(ip, hosts)| {
hosts
.filter(|host| {
let invalid = [
'\0', '\t', '\n', '\r', ' ', '#', '%', '/', ':', '?', '@', '[', '\\', ']',
];
host.parse::<Ipv4Addr>().is_err() && !host.contains(&invalid[..])
})
.map(move |host| (host.to_owned(), ip))
})
.collect()
}
pub fn replace_host(host: &str) -> Cow<'_, str> {
HOST_TABLE
.lock()
.as_ref()
.and_then(|table| table.get(host))
.map_or(host.into(), |replaced_host| {
replaced_host.to_string().into()
})
}