diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/file_upload.rs | 58 | ||||
-rw-r--r-- | src/main.rs | 54 |
2 files changed, 61 insertions, 51 deletions
diff --git a/src/file_upload.rs b/src/file_upload.rs index 273d12c..534083c 100644 --- a/src/file_upload.rs +++ b/src/file_upload.rs @@ -4,7 +4,7 @@ use actix_web::{ dev, http::header, multipart, FromRequest, FutureResponse, HttpMessage, HttpRequest, HttpResponse, Query, }; -use futures::{future, Future, Stream}; +use futures::{future, future::FutureResult, Future, Stream}; use serde::Deserialize; use std::{ fs, @@ -101,7 +101,15 @@ fn handle_multipart( /// invalid. /// This method returns future. pub fn upload_file(req: &HttpRequest<crate::MiniserveConfig>) -> FutureResponse<HttpResponse> { - let app_root_dir = req.state().path.clone().canonicalize().unwrap(); + let return_path: String = req.headers()[header::REFERER] + .to_str() + .unwrap_or("/") + .to_owned(); + 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 path = match Query::<QueryParameters>::extract(req) { Ok(query) => { if let Ok(stripped_path) = query.path.strip_prefix(Component::RootDir) { @@ -111,23 +119,17 @@ pub fn upload_file(req: &HttpRequest<crate::MiniserveConfig>) -> FutureResponse< } } Err(_) => { - return Box::new(future::ok( - HttpResponse::BadRequest().body("Unspecified parameter path"), + return Box::new(create_error_response( + "Unspecified parameter path", + &return_path, )) } }; - // this is really ugly I will try to think about something smarter - let return_path: String = req.headers()[header::REFERER] - .clone() - .to_str() - .unwrap_or("/") - .to_owned(); - let r_p2 = return_path.clone(); // If the target path is under the app root directory, save the file. - let target_dir = match &app_root_dir.clone().join(path.clone()).canonicalize() { + 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(future::ok(HttpResponse::BadRequest().body("Invalid path"))), + _ => return Box::new(create_error_response("Invalid path", &return_path)), }; let overwrite_files = req.state().overwrite_files; Box::new( @@ -136,17 +138,25 @@ pub fn upload_file(req: &HttpRequest<crate::MiniserveConfig>) -> FutureResponse< .map(move |item| handle_multipart(item, target_dir.clone(), overwrite_files)) .flatten() .collect() - .map(move |_| { - HttpResponse::TemporaryRedirect() - .header(header::LOCATION, return_path.to_string()) - .finish() - }) - .or_else(move |e| { - let error_description = format!("{}", e); - future::ok( - HttpResponse::BadRequest() - .body(file_upload_error(&error_description, &r_p2.clone()).into_string()), - ) + .then(move |e| match e { + Ok(_) => future::ok( + HttpResponse::SeeOther() + .header(header::LOCATION, return_path.to_string()) + .finish(), + ), + Err(e) => create_error_response(&e.to_string(), &return_path), }), ) } + +/// Convenience method for creating response errors, if file upload fails. +fn create_error_response( + description: &str, + return_path: &str, +) -> FutureResult<HttpResponse, actix_web::error::Error> { + future::ok( + HttpResponse::BadRequest() + .content_type("text/html; charset=utf-8") + .body(file_upload_error(description, return_path).into_string()), + ) +} diff --git a/src/main.rs b/src/main.rs index a703b00..fce9cf6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,33 +84,6 @@ fn main() { let sys = actix::System::new("miniserve"); let inside_config = miniserve_config.clone(); - server::new(move || { - App::with_state(inside_config.clone()) - .middleware(auth::Auth) - .middleware(middleware::Logger::default()) - .configure(configure_app) - }) - .bind( - miniserve_config - .interfaces - .iter() - .map(|interface| { - format!( - "{interface}:{port}", - interface = &interface, - port = miniserve_config.port, - ) - .to_socket_addrs() - .unwrap() - .next() - .unwrap() - }) - .collect::<Vec<SocketAddr>>() - .as_slice(), - ) - .expect("Couldn't bind server") - .shutdown_timeout(0) - .start(); let interfaces = miniserve_config.interfaces.iter().map(|&interface| { if interface == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) { @@ -181,6 +154,33 @@ fn main() { ); println!("\nQuit by pressing CTRL-C"); + server::new(move || { + App::with_state(inside_config.clone()) + .middleware(auth::Auth) + .middleware(middleware::Logger::default()) + .configure(configure_app) + }) + .bind( + miniserve_config + .interfaces + .iter() + .map(|interface| { + format!( + "{interface}:{port}", + interface = &interface, + port = miniserve_config.port, + ) + .to_socket_addrs() + .unwrap() + .next() + .unwrap() + }) + .collect::<Vec<SocketAddr>>() + .as_slice(), + ) + .expect("Couldn't bind server") + .shutdown_timeout(0) + .start(); let _ = sys.run(); } |