From 4e823e8bba1480c804f09e4ac88f47c0966b1f25 Mon Sep 17 00:00:00 2001 From: sigoden Date: Fri, 8 Jul 2022 19:30:05 +0800 Subject: [PATCH] feat: make --path-prefix works on serving single file (#102) --- src/args.rs | 3 ++- src/server.rs | 27 ++++++++++++++++++-- tests/args.rs | 24 +----------------- tests/single_file.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 tests/single_file.rs diff --git a/src/args.rs b/src/args.rs index e4815c1..bb06720 100644 --- a/src/args.rs +++ b/src/args.rs @@ -10,6 +10,7 @@ use crate::auth::AccessControl; use crate::auth::AuthMethod; #[cfg(feature = "tls")] use crate::tls::{load_certs, load_private_key}; +use crate::utils::encode_uri; use crate::BoxResult; pub fn build_cli() -> Command<'static> { @@ -196,7 +197,7 @@ impl Args { let uri_prefix = if path_prefix.is_empty() { "/".to_owned() } else { - format!("/{}/", &path_prefix) + format!("/{}/", &encode_uri(&path_prefix)) }; let hidden: String = matches .value_of("hidden") diff --git a/src/server.rs b/src/server.rs index 46e64df..456ed3d 100644 --- a/src/server.rs +++ b/src/server.rs @@ -45,15 +45,30 @@ const BUF_SIZE: usize = 65536; pub struct Server { args: Arc, assets_prefix: String, + single_file_req_paths: Vec, running: Arc, } impl Server { pub fn new(args: Arc, running: Arc) -> Self { let assets_prefix = format!("{}__dufs_v{}_", args.uri_prefix, env!("CARGO_PKG_VERSION")); + let single_file_req_paths = if args.path_is_file { + vec![ + args.uri_prefix.to_string(), + args.uri_prefix[0..args.uri_prefix.len() - 1].to_string(), + encode_uri(&format!( + "{}{}", + &args.uri_prefix, + get_file_name(&args.path) + )), + ] + } else { + vec![] + }; Self { args, running, + single_file_req_paths, assets_prefix, } } @@ -118,8 +133,16 @@ impl Server { let head_only = method == Method::HEAD; if self.args.path_is_file { - self.handle_send_file(&self.args.path, headers, head_only, &mut res) - .await?; + if self + .single_file_req_paths + .iter() + .any(|v| v.as_str() == req_path) + { + self.handle_send_file(&self.args.path, headers, head_only, &mut res) + .await?; + } else { + status_not_found(&mut res); + } return Ok(res); } diff --git a/tests/args.rs b/tests/args.rs index db61803..91e0eb1 100644 --- a/tests/args.rs +++ b/tests/args.rs @@ -3,11 +3,8 @@ mod fixtures; mod utils; -use assert_cmd::prelude::*; -use assert_fs::fixture::TempDir; -use fixtures::{port, server, tmpdir, wait_for_port, Error, TestServer}; +use fixtures::{server, Error, TestServer}; use rstest::rstest; -use std::process::{Command, Stdio}; #[rstest] fn path_prefix_index(#[with(&["--path-prefix", "xyz"])] server: TestServer) -> Result<(), Error> { @@ -33,22 +30,3 @@ fn path_prefix_propfind( assert!(text.contains("/xyz/")); Ok(()) } - -#[rstest] -#[case("index.html")] -fn serve_single_file(tmpdir: TempDir, port: u16, #[case] file: &str) -> Result<(), Error> { - let mut child = Command::cargo_bin("dufs")? - .arg(tmpdir.path().join(file)) - .arg("-p") - .arg(port.to_string()) - .stdout(Stdio::piped()) - .spawn()?; - - wait_for_port(port); - - let resp = reqwest::blocking::get(format!("http://localhost:{}/index.html", port))?; - assert_eq!(resp.text()?, "This is index.html"); - - child.kill()?; - Ok(()) -} diff --git a/tests/single_file.rs b/tests/single_file.rs new file mode 100644 index 0000000..1d97f3f --- /dev/null +++ b/tests/single_file.rs @@ -0,0 +1,60 @@ +//! Run file server with different args + +mod fixtures; +mod utils; + +use assert_cmd::prelude::*; +use assert_fs::fixture::TempDir; +use fixtures::{port, tmpdir, wait_for_port, Error}; +use rstest::rstest; +use std::process::{Command, Stdio}; + +#[rstest] +#[case("index.html")] +fn single_file(tmpdir: TempDir, port: u16, #[case] file: &str) -> Result<(), Error> { + let mut child = Command::cargo_bin("dufs")? + .arg(tmpdir.path().join(file)) + .arg("-p") + .arg(port.to_string()) + .stdout(Stdio::piped()) + .spawn()?; + + wait_for_port(port); + + let resp = reqwest::blocking::get(format!("http://localhost:{}", port))?; + assert_eq!(resp.text()?, "This is index.html"); + let resp = reqwest::blocking::get(format!("http://localhost:{}/", port))?; + assert_eq!(resp.text()?, "This is index.html"); + let resp = reqwest::blocking::get(format!("http://localhost:{}/index.html", port))?; + assert_eq!(resp.text()?, "This is index.html"); + + child.kill()?; + Ok(()) +} + +#[rstest] +#[case("index.html")] +fn path_prefix_single_file(tmpdir: TempDir, port: u16, #[case] file: &str) -> Result<(), Error> { + let mut child = Command::cargo_bin("dufs")? + .arg(tmpdir.path().join(file)) + .arg("-p") + .arg(port.to_string()) + .arg("--path-prefix") + .arg("xyz") + .stdout(Stdio::piped()) + .spawn()?; + + wait_for_port(port); + + let resp = reqwest::blocking::get(format!("http://localhost:{}/xyz", port))?; + assert_eq!(resp.text()?, "This is index.html"); + let resp = reqwest::blocking::get(format!("http://localhost:{}/xyz/", port))?; + assert_eq!(resp.text()?, "This is index.html"); + let resp = reqwest::blocking::get(format!("http://localhost:{}/xyz/index.html", port))?; + assert_eq!(resp.text()?, "This is index.html"); + let resp = reqwest::blocking::get(format!("http://localhost:{}", port))?; + assert_eq!(resp.status(), 404); + + child.kill()?; + Ok(()) +}