diff options
Diffstat (limited to '')
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/file_op.rs | 17 | ||||
-rw-r--r-- | tests/upload_files.rs | 4 |
5 files changed, 14 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index fb6d682..0e25460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate - Properly handle read-only errors on Windows [#1310](https://github.com/svenstaro/miniserve/pull/1310) (thanks @ViRb3) +- Use `tokio::fs` instead of `std::fs` to enable async file operations [#445](https://github.com/svenstaro/miniserve/issues/445) ## [0.25.0] - 2024-01-07 - Add `--pretty-urls` [#1193](https://github.com/svenstaro/miniserve/pull/1193) (thanks @nlopes) @@ -1769,6 +1769,7 @@ dependencies = [ "strum", "tar", "thiserror", + "tokio", "url", "zip", ] @@ -57,6 +57,7 @@ socket2 = "0.5" strum = { version = "0.25", features = ["derive"] } tar = "0.4" thiserror = "1" +tokio = { version = "1.35.1", features = ["fs"] } zip = { version = "0.6.5", default-features = false } [features] diff --git a/src/file_op.rs b/src/file_op.rs index 6537182..760b23e 100644 --- a/src/file_op.rs +++ b/src/file_op.rs @@ -1,14 +1,14 @@ //! Handlers for file upload and removal use std::io::ErrorKind; -use std::{ - io::Write, - path::{Component, Path, PathBuf}, -}; +use std::path::{Component, Path, PathBuf}; use actix_web::{http::header, web, HttpRequest, HttpResponse}; +use futures::TryFutureExt; use futures::TryStreamExt; use serde::Deserialize; +use tokio::fs::File; +use tokio::io::AsyncWriteExt; use crate::{ config::MiniserveConfig, errors::ContextualError, file_utils::contains_symlink, @@ -28,7 +28,7 @@ async fn save_file( return Err(ContextualError::DuplicateFileError); } - let file = match std::fs::File::create(&file_path) { + let file = match File::create(&file_path).await { Err(err) if err.kind() == ErrorKind::PermissionDenied => Err( ContextualError::InsufficientPermissionsError(file_path.display().to_string()), ), @@ -43,7 +43,8 @@ async fn save_file( .map_err(|x| ContextualError::MultipartError(x.to_string())) .try_fold((file, 0u64), |(mut file, written_len), bytes| async move { file.write_all(bytes.as_ref()) - .map_err(|e| ContextualError::IoError("Failed to write to file".to_string(), e))?; + .map_err(|e| ContextualError::IoError("Failed to write to file".to_string(), e)) + .await?; Ok((file, written_len + bytes.len() as u64)) }) .await?; @@ -62,7 +63,7 @@ async fn handle_multipart( ) -> Result<u64, ContextualError> { let field_name = field.name().to_string(); - match std::fs::metadata(&path) { + match tokio::fs::metadata(&path).await { Err(_) => Err(ContextualError::InsufficientPermissionsError( path.display().to_string(), )), @@ -132,7 +133,7 @@ async fn handle_multipart( } } - return match std::fs::create_dir_all(&absolute_path) { + return match tokio::fs::create_dir_all(&absolute_path).await { Err(err) if err.kind() == ErrorKind::PermissionDenied => Err( ContextualError::InsufficientPermissionsError(path.display().to_string()), ), diff --git a/tests/upload_files.rs b/tests/upload_files.rs index 8cb3e8e..77a9dc3 100644 --- a/tests/upload_files.rs +++ b/tests/upload_files.rs @@ -122,8 +122,8 @@ fn uploading_files_is_restricted(#[case] server: TestServer) -> Result<(), Error #[case(server(&["-u", "./-someDir"]), vec!["./-someDir"])] #[case(server(&["-u", Path::new("someDir/some_sub_dir").to_str().unwrap()]), vec!["someDir/some_sub_dir"])] -#[case(server(&["-u", Path::new("someDir/some_sub_dir").to_str().unwrap(), - "-u", Path::new("someDir/some_other_dir").to_str().unwrap()]), +#[case(server(&["-u", Path::new("someDir/some_sub_dir").to_str().unwrap(), + "-u", Path::new("someDir/some_other_dir").to_str().unwrap()]), vec!["someDir/some_sub_dir", "someDir/some_other_dir"])] fn uploading_files_to_allowed_dir_works( #[case] server: TestServer, |