aboutsummaryrefslogtreecommitdiffstats
path: root/src/file_upload.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/file_upload.rs')
-rw-r--r--src/file_upload.rs167
1 files changed, 25 insertions, 142 deletions
diff --git a/src/file_upload.rs b/src/file_upload.rs
index 6fa99ef..5f9738c 100644
--- a/src/file_upload.rs
+++ b/src/file_upload.rs
@@ -1,16 +1,12 @@
-use actix_web::{
- http::{header, StatusCode},
- HttpRequest, HttpResponse,
-};
+use actix_web::{http::header, HttpRequest, HttpResponse};
use futures::TryStreamExt;
use std::{
io::Write,
path::{Component, PathBuf},
};
-use crate::errors::{self, ContextualError};
-use crate::listing::{self, SortingMethod, SortingOrder};
-use crate::renderer;
+use crate::errors::ContextualError;
+use crate::listing::{self};
/// Create future to save file.
async fn save_file(
@@ -76,17 +72,10 @@ async fn handle_multipart(
/// server root directory. Any path which will go outside of this directory is considered
/// invalid.
/// This method returns future.
-#[allow(clippy::too_many_arguments)]
pub async fn upload_file(
req: HttpRequest,
payload: actix_web::web::Payload,
- uses_random_route: bool,
- favicon_route: String,
- css_route: String,
- default_color_scheme: String,
- default_color_scheme_dark: String,
- hide_version_footer: bool,
-) -> Result<HttpResponse, actix_web::Error> {
+) -> Result<HttpResponse, ContextualError> {
let conf = req.app_data::<crate::MiniserveConfig>().unwrap();
let return_path = if let Some(header) = req.headers().get(header::REFERER) {
header.to_str().unwrap_or("/").to_owned()
@@ -95,138 +84,32 @@ pub async fn upload_file(
};
let query_params = listing::extract_query_parameters(&req);
- let upload_path = match query_params.path.clone() {
- Some(path) => match path.strip_prefix(Component::RootDir) {
- Ok(stripped_path) => stripped_path.to_owned(),
- Err(_) => path.clone(),
- },
- None => {
- let err = ContextualError::InvalidHttpRequestError(
- "Missing query parameter 'path'".to_string(),
- );
- return Ok(create_error_response(
- &err.to_string(),
- StatusCode::BAD_REQUEST,
- &return_path,
- query_params.sort,
- query_params.order,
- uses_random_route,
- &favicon_route,
- &css_route,
- &default_color_scheme,
- &default_color_scheme_dark,
- hide_version_footer,
- ));
- }
- };
+ let upload_path = query_params.path.as_ref().ok_or_else(|| {
+ ContextualError::InvalidHttpRequestError("Missing query parameter 'path'".to_string())
+ })?;
+ let upload_path = upload_path
+ .strip_prefix(Component::RootDir)
+ .unwrap_or(upload_path);
- let app_root_dir = match conf.path.canonicalize() {
- Ok(dir) => dir,
- Err(e) => {
- let err = ContextualError::IoError(
- "Failed to resolve path served by miniserve".to_string(),
- e,
- );
- return Ok(create_error_response(
- &err.to_string(),
- StatusCode::INTERNAL_SERVER_ERROR,
- &return_path,
- query_params.sort,
- query_params.order,
- uses_random_route,
- &favicon_route,
- &css_route,
- &default_color_scheme,
- &default_color_scheme_dark,
- hide_version_footer,
- ));
- }
- };
+ let app_root_dir = conf.path.canonicalize().map_err(|e| {
+ ContextualError::IoError("Failed to resolve path served by miniserve".to_string(), e)
+ })?;
// If the target path is under the app root directory, save the file.
- let target_dir = match &app_root_dir.join(upload_path).canonicalize() {
- Ok(path) if path.starts_with(&app_root_dir) => path.clone(),
- _ => {
- let err = ContextualError::InvalidHttpRequestError(
- "Invalid value for 'path' parameter".to_string(),
- );
- return Ok(create_error_response(
- &err.to_string(),
- StatusCode::BAD_REQUEST,
- &return_path,
- query_params.sort,
- query_params.order,
- uses_random_route,
- &favicon_route,
- &css_route,
- &default_color_scheme,
- &default_color_scheme_dark,
- hide_version_footer,
- ));
- }
- };
- let overwrite_files = conf.overwrite_files;
- let default_color_scheme = conf.default_color_scheme.clone();
- let default_color_scheme_dark = conf.default_color_scheme_dark.clone();
+ let target_dir = match app_root_dir.join(upload_path).canonicalize() {
+ Ok(path) if path.starts_with(&app_root_dir) => Ok(path),
+ _ => Err(ContextualError::InvalidHttpRequestError(
+ "Invalid value for 'path' parameter".to_string(),
+ )),
+ }?;
- match actix_multipart::Multipart::new(req.headers(), payload)
+ actix_multipart::Multipart::new(req.headers(), payload)
.map_err(ContextualError::MultipartError)
- .and_then(move |field| handle_multipart(field, target_dir.clone(), overwrite_files))
+ .and_then(|field| handle_multipart(field, target_dir.clone(), conf.overwrite_files))
.try_collect::<Vec<u64>>()
- .await
- {
- Ok(_) => Ok(HttpResponse::SeeOther()
- .append_header((header::LOCATION, return_path))
- .finish()),
- Err(e) => Ok(create_error_response(
- &e.to_string(),
- StatusCode::INTERNAL_SERVER_ERROR,
- &return_path,
- query_params.sort,
- query_params.order,
- uses_random_route,
- &favicon_route,
- &css_route,
- &default_color_scheme,
- &default_color_scheme_dark,
- hide_version_footer,
- )),
- }
-}
+ .await?;
-/// Convenience method for creating response errors, if file upload fails.
-#[allow(clippy::too_many_arguments)]
-fn create_error_response(
- description: &str,
- error_code: StatusCode,
- return_path: &str,
- sorting_method: Option<SortingMethod>,
- sorting_order: Option<SortingOrder>,
- uses_random_route: bool,
- favicon_route: &str,
- css_route: &str,
- default_color_scheme: &str,
- default_color_scheme_dark: &str,
- hide_version_footer: bool,
-) -> HttpResponse {
- errors::log_error_chain(description.to_string());
- HttpResponse::BadRequest()
- .content_type("text/html; charset=utf-8")
- .body(
- renderer::render_error(
- description,
- error_code,
- return_path,
- sorting_method,
- sorting_order,
- true,
- !uses_random_route,
- favicon_route,
- css_route,
- default_color_scheme,
- default_color_scheme_dark,
- hide_version_footer,
- )
- .into_string(),
- )
+ Ok(HttpResponse::SeeOther()
+ .append_header((header::LOCATION, return_path))
+ .finish())
}