diff --git a/src/main.rs b/src/main.rs index c54639a7..602a4f11 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,7 +28,6 @@ use std::sync::Arc; use anyhow::{anyhow, Context, Result}; use atty::Stream; use cookie_store::{CookieStore, RawCookie}; -use network_interface::{NetworkInterface, NetworkInterfaceConfig}; use redirect::RedirectFollower; use reqwest::blocking::Client; use reqwest::header::{ @@ -45,7 +44,7 @@ use crate::middleware::ClientWithMiddleware; use crate::printer::Printer; use crate::request_items::{Body, FORM_CONTENT_TYPE, JSON_ACCEPT, JSON_CONTENT_TYPE}; use crate::session::Session; -use crate::utils::{test_mode, test_pretend_term, url_with_query}; +use crate::utils::{interface_name_to_ip, test_mode, test_pretend_term, url_with_query}; use crate::vendored::reqwest_cookie_store; #[cfg(not(any(feature = "native-tls", feature = "rustls")))] @@ -95,10 +94,7 @@ fn run(args: Cli) -> Result { return Ok(0); } - let warn = { - let bin_name = &args.bin_name; - move |msg| eprintln!("{}: warning: {}", bin_name, msg) - }; + let warn = |msg| eprintln!("{}: warning: {}", args.bin_name, msg); let (mut headers, headers_to_unset) = args.request_items.headers()?; let url = url_with_query(args.url, &args.request_items.query()?); @@ -289,17 +285,7 @@ fn run(args: Cli) -> Result { let ip_addr = if let Ok(ip_addr) = IpAddr::from_str(name_or_ip) { Some(ip_addr) } else { - // TODO: Directly bind to interface name once hyper/reqwest adds support for it. - // See https://github.com/seanmonstar/reqwest/issues/1336 and https://github.com/hyperium/hyper/pull/3076 - let network_interfaces = NetworkInterface::show()?; - network_interfaces.iter().find_map(|interface| { - if &interface.name == name_or_ip { - if let Some(addr) = interface.addr.first() { - return Some(addr.ip()); - } - } - None - }) + interface_name_to_ip(&name_or_ip)? }; if let Some(ip_addr) = ip_addr { diff --git a/src/utils.rs b/src/utils.rs index fe082c51..9488d087 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::env::var_os; use std::io::{self, Write}; +use std::net::IpAddr; use std::path::{Path, PathBuf}; use anyhow::Result; @@ -171,3 +172,37 @@ pub fn copy_largebuf( } } } + +#[cfg(any( + target_os = "linux", + target_os = "macos", + target_os = "windows", + target_os = "android" +))] +pub fn interface_name_to_ip(name: &str) -> Result> { + use network_interface::{NetworkInterface, NetworkInterfaceConfig}; + // TODO: Directly bind to interface name once hyper/reqwest adds support for it. + // See https://github.com/seanmonstar/reqwest/issues/1336 and https://github.com/hyperium/hyper/pull/3076 + let network_interfaces = NetworkInterface::show()?; + Ok(network_interfaces.iter().find_map(|interface| { + if &interface.name == name { + if let Some(addr) = interface.addr.first() { + return Some(addr.ip()); + } + } + None + })) +} + +#[cfg(not(any( + target_os = "linux", + target_os = "macos", + target_os = "windows", + target_os = "android" +)))] +pub fn interface_name_to_ip(_name: &str) -> Result> { + Err(anyhow::anyhow!( + "binding to interface name is not supported in {}", + std::env::consts::OS + )) +}