diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/args.rs | 8 | ||||
-rw-r--r-- | tests/serve_request.rs | 26 |
4 files changed, 36 insertions, 1 deletions
@@ -1753,6 +1753,7 @@ dependencies = [ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "port_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", "rstest 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "select 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -27,6 +27,7 @@ actix-web = "0.7" simplelog = "0.8" base64 = "0.12" percent-encoding = "2.1" +port_check = "0.1" htmlescape = "0.3.1" bytesize = "1.0.0" nanoid = "0.3" @@ -55,5 +56,6 @@ assert_fs = "1.0" select = "0.4" port_check = "0.1" rstest = "0.6" +regex = "1.3.9" pretty_assertions = "0.6" url = "2.1" diff --git a/src/args.rs b/src/args.rs index 7e30ee1..a5bcfea 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,6 +1,7 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::path::PathBuf; use structopt::StructOpt; +use port_check::free_local_port; use crate::auth; use crate::errors::ContextualError; @@ -170,10 +171,15 @@ pub fn parse_args() -> crate::MiniserveConfig { let path_explicitly_chosen = args.path.is_some(); + let port = match args.port { + 0 => free_local_port().expect("no free ports available"), + _ => args.port, + }; + crate::MiniserveConfig { verbose: args.verbose, path: args.path.unwrap_or_else(|| PathBuf::from(".")), - port: args.port, + port, interfaces, auth: args.auth, path_explicitly_chosen, diff --git a/tests/serve_request.rs b/tests/serve_request.rs index 5761a65..918bb98 100644 --- a/tests/serve_request.rs +++ b/tests/serve_request.rs @@ -9,6 +9,7 @@ use select::node::Node; use std::process::{Command, Stdio}; use std::thread::sleep; use std::time::Duration; +use regex::{Regex}; #[rstest] fn serves_requests_with_no_options(tmpdir: TempDir) -> Result<(), Error> { @@ -70,6 +71,31 @@ fn serves_requests_with_non_default_port(tmpdir: TempDir, port: u16) -> Result<( } #[rstest] +fn serves_requests_with_randomly_assigned_port(tmpdir: TempDir) -> Result<(), Error> { + let mut child = Command::cargo_bin("miniserve")? + .arg(tmpdir.path()) + .arg("-p") + .arg("0".to_string()) + .stdout(Stdio::piped()) + .spawn()?; + + sleep(Duration::from_secs(1)); + child.kill()?; + + let output = child.wait_with_output().expect("Failed to read stdout"); + let all_text = String::from_utf8(output.stdout)?; + + let re = Regex::new(r"http://127.0.0.1:(\d+)").unwrap(); + let caps = re.captures(all_text.as_str()).unwrap(); + let port_num = caps.get(1).unwrap().as_str().parse::<u32>().unwrap(); + + assert!(port_num > 0); + assert!(port_num <= 65535); + + Ok(()) +} + +#[rstest] fn serves_requests_custom_index_notice(tmpdir: TempDir, port: u16) -> Result<(), Error> { let mut child = Command::cargo_bin("miniserve")? .arg("--index=not.html") |