use std::path::Path;
use crate::bootstrap::{DaemonEndpoint, read_daemon_endpoint, read_daemon_endpoint_at};
pub fn daemon_url() -> String {
endpoint_to_url(&read_daemon_endpoint())
}
pub fn daemon_url_at(path: &Path) -> String {
endpoint_to_url(&read_daemon_endpoint_at(path))
}
fn endpoint_to_url(endpoint: &DaemonEndpoint) -> String {
let host = dial_host(&endpoint.host);
format!("http://{host}:{}", endpoint.port)
}
fn dial_host(host: &str) -> &str {
match host {
"0.0.0.0" | "::" | "::0" => "127.0.0.1",
other => other,
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::tempdir;
fn write_bootstrap(contents: &str) -> (tempfile::TempDir, std::path::PathBuf) {
let dir = tempdir().unwrap();
let path = dir.path().join("bootstrap.yaml");
fs::write(&path, contents).unwrap();
(dir, path)
}
#[test]
fn default_url_when_file_missing() {
let dir = tempdir().unwrap();
let path = dir.path().join("nope.yaml");
assert_eq!(daemon_url_at(&path), "http://127.0.0.1:60887");
}
#[test]
fn wildcard_ipv4_normalizes_to_loopback() {
let (_dir, path) = write_bootstrap("daemon_port: 60887\nbind_host: 0.0.0.0\n");
assert_eq!(daemon_url_at(&path), "http://127.0.0.1:60887");
}
#[test]
fn wildcard_ipv6_normalizes_to_loopback() {
let (_dir, path) = write_bootstrap(
r#"daemon_port: 60887
bind_host: "::"
"#,
);
assert_eq!(daemon_url_at(&path), "http://127.0.0.1:60887");
}
#[test]
fn wildcard_ipv6_zero_normalizes_to_loopback() {
let (_dir, path) = write_bootstrap(
r#"daemon_port: 60887
bind_host: "::0"
"#,
);
assert_eq!(daemon_url_at(&path), "http://127.0.0.1:60887");
}
#[test]
fn localhost_passes_through() {
let (_dir, path) = write_bootstrap("daemon_port: 60887\nbind_host: localhost\n");
assert_eq!(daemon_url_at(&path), "http://localhost:60887");
}
#[test]
fn custom_port_and_host_compose() {
let (_dir, path) = write_bootstrap("daemon_port: 61234\nbind_host: 10.0.0.5\n");
assert_eq!(daemon_url_at(&path), "http://10.0.0.5:61234");
}
}