aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/errors.rs4
-rw-r--r--src/file_upload.rs54
-rw-r--r--src/listing.rs5
3 files changed, 40 insertions, 23 deletions
diff --git a/src/errors.rs b/src/errors.rs
index 9f0a418..d34b447 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -68,6 +68,10 @@ pub enum ContextualErrorKind {
_0
)]
HTTPAuthenticationError(Box<ContextualError>),
+
+ /// This error might occur when an HTTP request is invalid
+ #[fail(display = "Invalid HTTP request\ncaused by: {}", _0)]
+ InvalidHTTPRequestError(String),
}
pub fn log_error_chain(description: String) {
diff --git a/src/file_upload.rs b/src/file_upload.rs
index 1618617..f444396 100644
--- a/src/file_upload.rs
+++ b/src/file_upload.rs
@@ -3,22 +3,16 @@ use actix_web::{
HttpResponse, Query,
};
use futures::{future, future::FutureResult, Future, Stream};
-use serde::Deserialize;
use std::{
fs,
io::Write,
path::{Component, PathBuf},
};
-use crate::errors::{self, ContextualErrorKind};
+use crate::errors::{self, ContextualError, ContextualErrorKind};
+use crate::listing::QueryParameters;
use crate::renderer;
-/// Query parameters
-#[derive(Debug, Deserialize)]
-struct QueryParameters {
- path: PathBuf,
-}
-
/// Create future to save file.
fn save_file(
field: multipart::Field<dev::Payload>,
@@ -127,31 +121,49 @@ pub fn upload_file(req: &HttpRequest<crate::MiniserveConfig>) -> FutureResponse<
} else {
"/".to_string()
};
- let app_root_dir = if let Ok(dir) = req.state().path.canonicalize() {
- dir
- } else {
- return Box::new(create_error_response("Internal server error", &return_path));
+
+ let app_root_dir = match req.state().path.canonicalize() {
+ Ok(dir) => dir,
+ Err(e) => {
+ let err = ContextualError::new(ContextualErrorKind::IOError(
+ "Failed to resolve path served by miniserve".to_string(),
+ e,
+ ));
+ return Box::new(create_error_response(&err.to_string(), &return_path));
+ }
};
+
let path = match Query::<QueryParameters>::extract(req) {
Ok(query) => {
- if let Ok(stripped_path) = query.path.strip_prefix(Component::RootDir) {
- stripped_path.to_owned()
+ if let Some(path) = query.path.clone() {
+ if let Ok(stripped_path) = path.strip_prefix(Component::RootDir) {
+ stripped_path.to_owned()
+ } else {
+ path.clone()
+ }
} else {
- query.path.clone()
+ let err = ContextualError::new(ContextualErrorKind::InvalidHTTPRequestError(
+ "Missing query parameter 'path'".to_string(),
+ ));
+ return Box::new(create_error_response(&err.to_string(), &return_path));
}
}
- Err(_) => {
- return Box::new(create_error_response(
- "Unspecified parameter path",
- &return_path,
- ))
+ Err(e) => {
+ let err =
+ ContextualError::new(ContextualErrorKind::InvalidHTTPRequestError(e.to_string()));
+ return Box::new(create_error_response(&err.to_string(), &return_path));
}
};
// If the target path is under the app root directory, save the file.
let target_dir = match &app_root_dir.clone().join(path).canonicalize() {
Ok(path) if path.starts_with(&app_root_dir) => path.clone(),
- _ => return Box::new(create_error_response("Invalid path", &return_path)),
+ _ => {
+ let err = ContextualError::new(ContextualErrorKind::InvalidHTTPRequestError(
+ "Invalid value for 'path' parameter".to_string(),
+ ));
+ return Box::new(create_error_response(&err.to_string(), &return_path));
+ }
};
let overwrite_files = req.state().overwrite_files;
Box::new(
diff --git a/src/listing.rs b/src/listing.rs
index a030feb..e718702 100644
--- a/src/listing.rs
+++ b/src/listing.rs
@@ -5,7 +5,7 @@ use htmlescape::encode_minimal as escape_html_entity;
use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
use serde::Deserialize;
use std::io;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::time::SystemTime;
use strum_macros::{Display, EnumString};
@@ -16,7 +16,8 @@ use crate::themes;
/// Query parameters
#[derive(Deserialize)]
-struct QueryParameters {
+pub struct QueryParameters {
+ pub path: Option<PathBuf>,
sort: Option<SortingMethod>,
order: Option<SortingOrder>,
download: Option<archive::CompressionMethod>,