aboutsummaryrefslogtreecommitdiffstats
path: root/src/listing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/listing.rs')
-rw-r--r--src/listing.rs76
1 files changed, 38 insertions, 38 deletions
diff --git a/src/listing.rs b/src/listing.rs
index 2ffcf2f..ba2e58e 100644
--- a/src/listing.rs
+++ b/src/listing.rs
@@ -1,7 +1,7 @@
-use actix_web::http::StatusCode;
-use actix_web::{fs, http, Body, FromRequest, HttpRequest, HttpResponse, Query, Result};
+use actix_web::{fs, Body, FromRequest, HttpRequest, HttpResponse, Query, Result};
use bytesize::ByteSize;
-use futures::stream::once;
+use failure::Fail;
+use futures::Stream;
use htmlescape::encode_minimal as escape_html_entity;
use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
use serde::Deserialize;
@@ -235,46 +235,46 @@ pub fn directory_listing<S>(
let color_scheme = query_params.theme.unwrap_or(default_color_scheme);
- if let Some(compression_method) = &query_params.download {
+ if let Some(compression_method) = query_params.download {
log::info!(
"Creating an archive ({extension}) of {path}...",
extension = compression_method.extension(),
path = &dir.path.display().to_string()
);
- match compression_method.create_archive(&dir.path, skip_symlinks) {
- Ok((filename, content)) => {
- log::info!("{file} successfully created !", file = &filename);
- Ok(HttpResponse::Ok()
- .content_type(compression_method.content_type())
- .content_encoding(compression_method.content_encoding())
- .header("Content-Transfer-Encoding", "binary")
- .header(
- "Content-Disposition",
- format!("attachment; filename={:?}", filename),
- )
- .chunked()
- .body(Body::Streaming(Box::new(once(Ok(content))))))
- }
- Err(err) => {
- errors::log_error_chain(err.to_string());
- Ok(HttpResponse::Ok()
- .status(http::StatusCode::INTERNAL_SERVER_ERROR)
- .body(
- renderer::render_error(
- &err.to_string(),
- StatusCode::INTERNAL_SERVER_ERROR,
- serve_path,
- query_params.sort,
- query_params.order,
- color_scheme,
- default_color_scheme,
- false,
- true,
- )
- .into_string(),
- ))
+
+ let filename = format!(
+ "{}.{}",
+ dir.path.file_name().unwrap().to_str().unwrap(),
+ compression_method.extension()
+ );
+
+ // Create a pipe to connect the archive creation thread and the response.
+ // Include 10 messages of buffer for erratic connection speeds.
+ let (tx, rx) = futures::sync::mpsc::channel(10);
+ let pipe = crate::pipe::Pipe::new(tx);
+
+ // Start the actual archive creation in a separate thread.
+ let dir = dir.path.to_path_buf();
+ std::thread::spawn(move || {
+ if let Err(err) = compression_method.create_archive(dir, skip_symlinks, pipe) {
+ log::error!("Error during archive creation: {:?}", err);
}
- }
+ });
+
+ // `<rx as Stream>::Error == ()` but we want `actix_web::error::Error`
+ // It can't happen, so let's just please the type checker.
+ let rx = rx.map_err(|_| unreachable!("pipes never fail"));
+
+ Ok(HttpResponse::Ok()
+ .content_type(compression_method.content_type())
+ .content_encoding(compression_method.content_encoding())
+ .header("Content-Transfer-Encoding", "binary")
+ .header(
+ "Content-Disposition",
+ format!("attachment; filename={:?}", filename),
+ )
+ .chunked()
+ .body(Body::Streaming(Box::new(rx))))
} else {
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
@@ -302,7 +302,7 @@ pub fn extract_query_parameters<S>(req: &HttpRequest<S>) -> QueryParameters {
Ok(query) => QueryParameters {
sort: query.sort,
order: query.order,
- download: query.download.clone(),
+ download: query.download,
theme: query.theme,
path: query.path.clone(),
},