From c1b2c7706a1cbe344e9b29da98a5275daa23e40d Mon Sep 17 00:00:00 2001 From: "Aode (Lion)" Date: Thu, 9 Sep 2021 16:35:07 -0500 Subject: [PATCH] Add back range header support for thumbnail on generation --- src/main.rs | 41 ++++++++++++++++++++++++++++++++++------- src/range.rs | 17 ++++++++++++++++- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2112f72..be767b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -541,13 +541,40 @@ async fn process( let (details, bytes) = CancelSafeProcessor::new(thumbnail_path.clone(), Box::pin(process_fut)).await?; - return Ok(srv_response( - HttpResponse::Ok(), - once(ready(Ok(bytes) as Result<_, UploadError>)), - details.content_type(), - 7 * DAYS, - details.system_time(), - )); + return match range { + Some(range_header) => { + if !range_header.is_bytes() { + return Err(UploadError::Range); + } + + if range_header.is_empty() { + Err(UploadError::Range) + } else if range_header.len() == 1 { + let range = range_header.ranges().next().unwrap(); + let content_range = range.to_content_range(bytes.len() as u64); + let stream = range.chop_bytes(bytes); + let mut builder = HttpResponse::PartialContent(); + builder.insert_header(content_range); + + Ok(srv_response( + builder, + stream, + details.content_type(), + 7 * DAYS, + details.system_time(), + )) + } else { + Err(UploadError::Range) + } + } + None => Ok(srv_response( + HttpResponse::Ok(), + once(ready(Ok(bytes) as Result<_, UploadError>)), + details.content_type(), + 7 * DAYS, + details.system_time(), + )), + }; } let details = if let Some(details) = details { diff --git a/src/range.rs b/src/range.rs index 03695ee..81b9e11 100644 --- a/src/range.rs +++ b/src/range.rs @@ -8,7 +8,7 @@ use actix_web::{ web::Bytes, FromRequest, HttpRequest, }; -use futures_util::stream::LocalBoxStream; +use futures_util::stream::{once, LocalBoxStream, Stream}; use std::{future::ready, io}; use tokio::io::{AsyncReadExt, AsyncSeekExt}; @@ -43,6 +43,21 @@ impl Range { } } + pub(crate) fn chop_bytes( + &self, + bytes: Bytes, + ) -> impl Stream> + Unpin { + match self { + Range::RangeStart(start) => once(ready(Ok(bytes.slice(*start as usize..)))), + Range::SuffixLength(from_start) => { + once(ready(Ok(bytes.slice(..*from_start as usize)))) + } + Range::Segment(start, end) => { + once(ready(Ok(bytes.slice(*start as usize..*end as usize)))) + } + } + } + pub(crate) async fn chop_file( &self, mut file: tokio::fs::File,