use `?simple` to output path name only.
use `?json` to output paths in json format.
By default, output html page.
close #166
curl -X DELETE http://127.0.0.1:5000/path-to-file-or-folder
```
+List/search directory contents
+
+```
+curl http://127.0.0.1:5000?simple # output pathname only, just like `ls -1`
+
+curl http://127.0.0.1:5000?json # output name/mtime/type/size and other information in json format
+
+curl http://127.0.0.1:5000?q=Dockerfile&simple # search for files, just like `find -name Dockerfile`
+```
+
<details>
<summary><h2>Advanced topics</h2></summary>
} else {
paths.sort_unstable();
}
+ if query_params.contains_key("simple") {
+ let output = paths
+ .into_iter()
+ .map(|v| {
+ if v.is_dir() {
+ format!("{}/\n", v.name)
+ } else {
+ format!("{}\n", v.name)
+ }
+ })
+ .collect::<Vec<String>>()
+ .join("");
+ res.headers_mut()
+ .typed_insert(ContentType::from(mime_guess::mime::TEXT_HTML_UTF_8));
+ res.headers_mut()
+ .typed_insert(ContentLength(output.as_bytes().len() as u64));
+ *res.body_mut() = output.into();
+ if head_only {
+ return Ok(());
+ }
+ return Ok(());
+ }
let href = format!("/{}", normalize_path(path.strip_prefix(&self.args.path)?));
let data = IndexData {
href,
uri_prefix: self.args.uri_prefix.clone(),
- paths,
allow_upload: self.args.allow_upload,
allow_delete: self.args.allow_delete,
allow_search: self.args.allow_search,
allow_archive: self.args.allow_archive,
dir_exists: exist,
+ paths,
+ };
+ let output = if query_params.contains_key("json") {
+ res.headers_mut()
+ .typed_insert(ContentType::from(mime_guess::mime::APPLICATION_JSON));
+ serde_json::to_string_pretty(&data).unwrap()
+ } else {
+ res.headers_mut()
+ .typed_insert(ContentType::from(mime_guess::mime::TEXT_HTML_UTF_8));
+ self.html
+ .replace("__ASSERTS_PREFIX__", &self.assets_prefix)
+ .replace("__INDEX_DATA__", &serde_json::to_string(&data).unwrap())
};
- let data = serde_json::to_string(&data).unwrap();
- let output = self
- .html
- .replace("__ASSERTS_PREFIX__", &self.assets_prefix)
- .replace("__INDEX_DATA__", &data);
- res.headers_mut()
- .typed_insert(ContentType::from(mime_guess::mime::TEXT_HTML_UTF_8));
res.headers_mut()
.typed_insert(ContentLength(output.as_bytes().len() as u64));
if head_only {
struct IndexData {
href: String,
uri_prefix: String,
- paths: Vec<PathItem>,
allow_upload: bool,
allow_delete: bool,
allow_search: bool,
allow_archive: bool,
dir_exists: bool,
+ paths: Vec<PathItem>,
}
#[derive(Debug, Serialize, Eq, PartialEq, Ord, PartialOrd)]
fn assets(server: TestServer) -> Result<(), Error> {
let ver = env!("CARGO_PKG_VERSION");
let resp = reqwest::blocking::get(server.url())?;
- let index_js = format!("/__dufs_v{}_index.js", ver);
- let index_css = format!("/__dufs_v{}_index.css", ver);
- let favicon_ico = format!("/__dufs_v{}_favicon.ico", ver);
+ let index_js = format!("/__dufs_v{ver}_index.js");
+ let index_css = format!("/__dufs_v{ver}_index.css");
+ let favicon_ico = format!("/__dufs_v{ver}_favicon.ico");
let text = resp.text()?;
- assert!(text.contains(&format!(r#"href="{}""#, index_css)));
- assert!(text.contains(&format!(r#"href="{}""#, favicon_ico)));
- assert!(text.contains(&format!(r#"src="{}""#, index_js)));
+ assert!(text.contains(&format!(r#"href="{index_css}""#)));
+ assert!(text.contains(&format!(r#"href="{favicon_ico}""#)));
+ assert!(text.contains(&format!(r#"src="{index_js}""#)));
Ok(())
}
fn assets_with_prefix(#[with(&["--path-prefix", "xyz"])] server: TestServer) -> Result<(), Error> {
let ver = env!("CARGO_PKG_VERSION");
let resp = reqwest::blocking::get(format!("{}xyz/", server.url()))?;
- let index_js = format!("/xyz/__dufs_v{}_index.js", ver);
- let index_css = format!("/xyz/__dufs_v{}_index.css", ver);
- let favicon_ico = format!("/xyz/__dufs_v{}_favicon.ico", ver);
+ let index_js = format!("/xyz/__dufs_v{ver}_index.js");
+ let index_css = format!("/xyz/__dufs_v{ver}_index.css");
+ let favicon_ico = format!("/xyz/__dufs_v{ver}_favicon.ico");
let text = resp.text()?;
- assert!(text.contains(&format!(r#"href="{}""#, index_css)));
- assert!(text.contains(&format!(r#"href="{}""#, favicon_ico)));
- assert!(text.contains(&format!(r#"src="{}""#, index_js)));
+ assert!(text.contains(&format!(r#"href="{index_css}""#)));
+ assert!(text.contains(&format!(r#"href="{favicon_ico}""#)));
+ assert!(text.contains(&format!(r#"src="{index_js}""#)));
Ok(())
}
wait_for_port(port);
- let url = format!("http://localhost:{}", port);
+ let url = format!("http://localhost:{port}");
let resp = reqwest::blocking::get(&url)?;
assert!(resp.text()?.starts_with(&format!(
"/__dufs_v{}_index.js;DATA",
for file in FILES {
tmpdir
.child(file)
- .write_str(&format!("This is {}", file))
+ .write_str(&format!("This is {file}"))
.expect("Couldn't write to file");
}
for directory in DIRECTORIES {
continue;
}
tmpdir
- .child(format!("{}{}", directory, file))
- .write_str(&format!("This is {}{}", directory, file))
+ .child(format!("{directory}{file}"))
+ .write_str(&format!("This is {directory}{file}"))
.expect("Couldn't write to file");
}
}
pub fn wait_for_port(port: u16) {
let start_wait = Instant::now();
- while !port_check::is_port_reachable(format!("localhost:{}", port)) {
+ while !port_check::is_port_reachable(format!("localhost:{port}")) {
sleep(Duration::from_millis(100));
if start_wait.elapsed().as_secs() > 1 {
- panic!("timeout waiting for port {}", port);
+ panic!("timeout waiting for port {port}");
}
}
}
use fixtures::{server, Error, TestServer};
use rstest::rstest;
+use serde_json::Value;
#[rstest]
fn get_dir(server: TestServer) -> Result<(), Error> {
Ok(())
}
+#[rstest]
+fn get_dir_json(#[with(&["-A"])] server: TestServer) -> Result<(), Error> {
+ let resp = reqwest::blocking::get(format!("{}?json", server.url()))?;
+ assert_eq!(resp.status(), 200);
+ assert_eq!(
+ resp.headers().get("content-type").unwrap(),
+ "application/json"
+ );
+ let json: Value = serde_json::from_str(&resp.text().unwrap()).unwrap();
+ assert!(json["paths"].as_array().is_some());
+ Ok(())
+}
+
+#[rstest]
+fn get_dir_simple(#[with(&["-A"])] server: TestServer) -> Result<(), Error> {
+ let resp = reqwest::blocking::get(format!("{}?simple", server.url()))?;
+ assert_eq!(resp.status(), 200);
+ assert_eq!(
+ resp.headers().get("content-type").unwrap(),
+ "text/html; charset=utf-8"
+ );
+ let text = resp.text().unwrap();
+ assert!(text.split('\n').any(|v| v == "index.html"));
+ Ok(())
+}
+
#[rstest]
fn head_dir_zip(#[with(&["-A"])] server: TestServer) -> Result<(), Error> {
let resp = fetch!(b"HEAD", format!("{}?zip", server.url())).send()?;
Ok(())
}
+#[rstest]
+fn get_dir_search3(#[with(&["-A"])] server: TestServer) -> Result<(), Error> {
+ let resp = reqwest::blocking::get(format!("{}?q={}&simple", server.url(), "test.html"))?;
+ assert_eq!(resp.status(), 200);
+ let text = resp.text().unwrap();
+ assert!(text.split('\n').any(|v| v == "test.html"));
+ Ok(())
+}
+
#[rstest]
fn head_dir_search(#[with(&["-A"])] server: TestServer) -> Result<(), Error> {
let resp = fetch!(b"HEAD", format!("{}?q={}", server.url(), "test.html")).send()?;
let stdout = child.stdout.as_mut().expect("Failed to get stdout");
- let req = fetch!(b"GET", &format!("http://localhost:{}", port));
+ let req = fetch!(b"GET", &format!("http://localhost:{port}"));
let resp = if is_basic {
req.basic_auth("user", Some("pass")).send()?
let stdout = child.stdout.as_mut().expect("Failed to get stdout");
- let resp = fetch!(b"GET", &format!("http://localhost:{}", port)).send()?;
+ let resp = fetch!(b"GET", &format!("http://localhost:{port}")).send()?;
assert_eq!(resp.status(), 200);
let mut buf = [0; 1000];
wait_for_port(port);
- let resp = reqwest::blocking::get(format!("http://localhost:{}", 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))?;
+ 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))?;
+ let resp = reqwest::blocking::get(format!("http://localhost:{port}/index.html"))?;
assert_eq!(resp.text()?, "This is index.html");
child.kill()?;
wait_for_port(port);
- let resp = reqwest::blocking::get(format!("http://localhost:{}/xyz", port))?;
+ let resp = reqwest::blocking::get(format!("http://localhost:{port}/xyz"))?;
assert_eq!(resp.text()?, "This is index.html");
- let resp = reqwest::blocking::get(format!("http://localhost:{}/xyz/", port))?;
+ let resp = reqwest::blocking::get(format!("http://localhost:{port}/xyz/"))?;
assert_eq!(resp.text()?, "This is index.html");
- let resp = reqwest::blocking::get(format!("http://localhost:{}/xyz/index.html", port))?;
+ let resp = reqwest::blocking::get(format!("http://localhost:{port}/xyz/index.html"))?;
assert_eq!(resp.text()?, "This is index.html");
- let resp = reqwest::blocking::get(format!("http://localhost:{}", port))?;
+ let resp = reqwest::blocking::get(format!("http://localhost:{port}"))?;
assert_eq!(resp.status(), 404);
child.kill()?;
#[rstest]
fn ls_dir_sort_by_name(server: TestServer) -> Result<(), Error> {
let url = server.url();
- let resp = reqwest::blocking::get(format!("{}?sort=name&order=asc", url))?;
+ let resp = reqwest::blocking::get(format!("{url}?sort=name&order=asc"))?;
let paths1 = self::utils::retrieve_index_paths(&resp.text()?);
- let resp = reqwest::blocking::get(format!("{}?sort=name&order=desc", url))?;
+ let resp = reqwest::blocking::get(format!("{url}?sort=name&order=desc"))?;
let mut paths2 = self::utils::retrieve_index_paths(&resp.text()?);
paths2.reverse();
assert_eq!(paths1, paths2);
#[rstest]
fn search_dir_sort_by_name(server: TestServer) -> Result<(), Error> {
let url = server.url();
- let resp = reqwest::blocking::get(format!("{}?q={}&sort=name&order=asc", url, "test.html"))?;
+ let resp = reqwest::blocking::get(format!("{url}?q=test.html&sort=name&order=asc"))?;
let paths1 = self::utils::retrieve_index_paths(&resp.text()?);
- let resp = reqwest::blocking::get(format!("{}?q={}&sort=name&order=desc", url, "test.html"))?;
+ let resp = reqwest::blocking::get(format!("{url}?q=test.html&sort=name&order=desc"))?;
let mut paths2 = self::utils::retrieve_index_paths(&resp.text()?);
paths2.reverse();
assert_eq!(paths1, paths2);
let resp = reqwest::blocking::get(server.url())?;
let paths = utils::retrieve_index_paths(&resp.text()?);
assert!(!paths.is_empty());
- assert!(!paths.contains(&format!("{}/", dir)));
+ assert!(!paths.contains(&format!("{dir}/")));
Ok(())
}
let resp = reqwest::blocking::get(server.url())?;
let paths = utils::retrieve_index_paths(&resp.text()?);
assert!(!paths.is_empty());
- assert!(paths.contains(&format!("{}/", dir)));
+ assert!(paths.contains(&format!("{dir}/")));
Ok(())
}
let name = v.get("name")?.as_str()?;
let path_type = v.get("path_type")?.as_str()?;
if path_type.ends_with("Dir") {
- Some(format!("{}/", name))
+ Some(format!("{name}/"))
} else {
Some(name.to_owned())
}