Show IP addresses of all local interfaces

.. when binding to wildcard addresses (:: or 0.0.0.0)

* Remove local variable `interfaces` because it is no longer used
multiple times.
This commit is contained in:
Ali MJ Al-Nasrawy 2021-05-07 18:29:10 +03:00
parent 28da05437d
commit 5692a9740c
2 changed files with 43 additions and 47 deletions

View File

@ -54,6 +54,7 @@ bytes = "1"
atty = "0.2"
rustls = { version = "0.19", optional = true }
socket2 = "0.4"
get_if_addrs = "0.5"
[features]
default = ["tls"]

View File

@ -1,6 +1,6 @@
use std::io;
use std::io::Write;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener};
use std::net::{IpAddr, SocketAddr, TcpListener};
use std::thread;
use std::time::Duration;
@ -102,23 +102,6 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), ContextualError> {
let inside_config = miniserve_config.clone();
let interfaces = miniserve_config
.interfaces
.iter()
.map(|&interface| {
if interface == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
// If the interface is 0.0.0.0, we'll change it to 127.0.0.1 so that clicking the link will
// also work on Windows. Why can't Windows interpret 0.0.0.0?
"127.0.0.1".to_string()
} else if interface.is_ipv6() {
// If the interface is IPv6 then we'll print it with brackets so that it is clickable.
format!("[{}]", interface)
} else {
format!("{}", interface)
}
})
.collect::<Vec<String>>();
let canon_path = miniserve_config.path.canonicalize().map_err(|e| {
ContextualError::IoError("Failed to resolve path to be served".to_string(), e)
})?;
@ -164,37 +147,49 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), ContextualError> {
thread::sleep(Duration::from_millis(500));
}
}
let mut addresses = String::new();
for interface in &interfaces {
if !addresses.is_empty() {
addresses.push_str(", ");
}
let protocol = if miniserve_config.tls_rustls_config.is_some() {
"https"
} else {
"http"
};
addresses.push_str(&format!(
"{}",
Color::Green
.paint(format!(
"{protocol}://{interface}:{port}",
protocol = protocol,
interface = &interface,
port = miniserve_config.port
))
.bold()
));
if let Some(random_route) = miniserve_config.clone().random_route {
addresses.push_str(&format!(
"{}",
Color::Green
.paint(format!("/{random_route}", random_route = random_route,))
.bold()
));
let addresses = {
let (mut ifaces, wildcard): (Vec<_>, Vec<_>) = miniserve_config
.interfaces
.clone()
.into_iter()
.partition(|addr| !addr.is_unspecified());
// Replace wildcard addresses with local interface addresses
if !wildcard.is_empty() {
let all_ipv4 = wildcard.iter().any(|addr| addr.is_ipv4());
let all_ipv6 = wildcard.iter().any(|addr| addr.is_ipv6());
ifaces = get_if_addrs::get_if_addrs()
.unwrap_or_else(|e| {
error!("Failed to get local interface addresses: {}", e);
Default::default()
})
.into_iter()
.map(|iface| iface.ip())
.filter(|ip| (all_ipv4 && ip.is_ipv4()) || (all_ipv6 && ip.is_ipv6()))
.collect();
ifaces.sort();
}
}
let urls = ifaces
.into_iter()
.map(|addr| match addr {
IpAddr::V4(_) => format!("{}:{}", addr, miniserve_config.port),
IpAddr::V6(_) => format!("[{}]:{}", addr, miniserve_config.port),
})
.map(|addr| match miniserve_config.tls_rustls_config {
Some(_) => format!("https://{}", addr),
None => format!("http://{}", addr),
})
.map(|url| match miniserve_config.random_route {
Some(ref random_route) => format!("{}/{}", url, random_route),
None => url,
})
.map(|url| Color::Green.paint(url).bold().to_string())
.collect::<Vec<_>>();
urls.join(", ")
};
let socket_addresses = miniserve_config
.interfaces