aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/file_upload.rs58
-rw-r--r--src/main.rs54
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();
}