From 5c09120c232ac8ffc0b194c8002373c70eaf359e Mon Sep 17 00:00:00 2001 From: 409 <409dev@protonmail.com> Date: Sat, 6 Sep 2025 18:00:58 +0200 Subject: [PATCH] improve file streams --- .../src/lib/domain/warren/models/file/mod.rs | 32 +++++++++++++++---- .../lib/inbound/http/handlers/warrens/mod.rs | 14 +++++--- backend/src/lib/outbound/file_system.rs | 21 ++++++++++-- frontend/lib/api/warrens.ts | 2 +- 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/backend/src/lib/domain/warren/models/file/mod.rs b/backend/src/lib/domain/warren/models/file/mod.rs index 8603e32..f1c67b8 100644 --- a/backend/src/lib/domain/warren/models/file/mod.rs +++ b/backend/src/lib/domain/warren/models/file/mod.rs @@ -116,11 +116,19 @@ pub enum FileType { pub struct FileMimeType(String); impl FileMimeType { + pub fn new_raw(raw: &str) -> Self { + Self(raw.to_owned()) + } + pub fn from_name(name: &str) -> Option { mime_guess::from_path(name) .first_raw() .map(|s| Self(s.to_owned())) } + + pub fn as_str(&self) -> &str { + self.0.as_str() + } } /// A valid file path that might start with a slash @@ -289,27 +297,39 @@ impl From for FilePath { pub type FileStreamInner = Box> + Send + Sync + Unpin + 'static>; -pub struct FileStream(FileType, FileStreamInner); +pub struct FileStream { + file_type: FileType, + mime_type: Option, + stream: FileStreamInner, +} impl FileStream { - pub fn new(file_type: FileType, stream: S) -> Self + pub fn new(file_type: FileType, mime_type: Option, stream: S) -> Self where S: Stream> + Send + Sync + Unpin + 'static, { - Self(file_type, Box::new(stream)) + Self { + file_type, + mime_type, + stream: Box::new(stream), + } } pub fn file_type(&self) -> FileType { - self.0 + self.file_type + } + + pub fn mime_type(&self) -> Option<&FileMimeType> { + self.mime_type.as_ref() } pub fn stream(&self) -> &FileStreamInner { - &self.1 + &self.stream } } impl From for FileStreamInner { fn from(value: FileStream) -> Self { - value.1 + value.stream } } diff --git a/backend/src/lib/inbound/http/handlers/warrens/mod.rs b/backend/src/lib/inbound/http/handlers/warrens/mod.rs index b018177..ca5251a 100644 --- a/backend/src/lib/inbound/http/handlers/warrens/mod.rs +++ b/backend/src/lib/inbound/http/handlers/warrens/mod.rs @@ -76,18 +76,22 @@ impl IntoResponse for FileStream { let mut builder = Response::builder().header(http::header::TRANSFER_ENCODING, "chunked"); if let Some(headers) = builder.headers_mut() { - if self.file_type() == FileType::Directory { + if let Some(mime_type) = self.mime_type() { headers.insert( http::header::CONTENT_TYPE, - HeaderValue::from_str("application/zip").unwrap(), + HeaderValue::from_str(mime_type.as_str()).unwrap(), ); } - headers.remove(http::header::CONTENT_LENGTH); + headers.insert( + http::header::TRANSFER_ENCODING, + HeaderValue::from_str("chunked").unwrap(), + ); } - let inner: FileStreamInner = self.into(); - builder.body(axum::body::Body::from_stream(inner)).unwrap() + builder + .body(axum::body::Body::from_stream(FileStreamInner::from(self))) + .unwrap() } } diff --git a/backend/src/lib/outbound/file_system.rs b/backend/src/lib/outbound/file_system.rs index e9ede83..d0692a0 100644 --- a/backend/src/lib/outbound/file_system.rs +++ b/backend/src/lib/outbound/file_system.rs @@ -265,7 +265,11 @@ impl FileSystem { } }); - FileStream::new(FileType::Directory, ReceiverStream::new(rx)) + FileStream::new( + FileType::Directory, + Some(FileMimeType::new_raw("application/zip")), + ReceiverStream::new(rx), + ) } match path_request { @@ -293,7 +297,20 @@ impl FileSystem { bail!("File size exceeds configured limit"); } - let stream = FileStream::new(FileType::File, ReaderStream::new(file)); + let mime_type = { + let file_name = { + let path = file_path.as_str(); + if let Some(last_slash_index) = path.rfind("/") { + &path[last_slash_index + 1..] + } else { + path + } + }; + + FileMimeType::from_name(file_name) + }; + + let stream = FileStream::new(FileType::File, mime_type, ReaderStream::new(file)); Ok(stream) } diff --git a/frontend/lib/api/warrens.ts b/frontend/lib/api/warrens.ts index cf45dfd..8f00430 100644 --- a/frontend/lib/api/warrens.ts +++ b/frontend/lib/api/warrens.ts @@ -38,7 +38,7 @@ export async function getWarrenDirectory( warrenId, path, }), - key: `${warrenId}-${path}`, + key: `${warrenId}-${path}`, }); if (data.value == null) {