1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-06-26 06:57:43 +02:00

fix master branch build. change web::block output type. (#1957)

This commit is contained in:
fakeshadow
2021-02-06 08:23:59 -08:00
committed by GitHub
parent 83fb4978ad
commit 20cf0094e5
17 changed files with 98 additions and 114 deletions

View File

@ -31,5 +31,5 @@ percent-encoding = "2.1"
v_htmlescape = "0.12"
[dev-dependencies]
actix-rt = "2.0.0-beta.2"
actix-rt = "=2.0.0-beta.2"
actix-web = "4.0.0-beta.1"

View File

@ -8,7 +8,7 @@ use std::{
};
use actix_web::{
error::{Error, ErrorInternalServerError},
error::{BlockingError, Error},
rt::task::{spawn_blocking, JoinHandle},
};
use bytes::Bytes;
@ -18,11 +18,26 @@ use futures_core::{ready, Stream};
/// A helper created from a `std::fs::File` which reads the file
/// chunk-by-chunk on a `ThreadPool`.
pub struct ChunkedReadFile {
pub(crate) size: u64,
pub(crate) offset: u64,
pub(crate) file: Option<File>,
pub(crate) fut: Option<JoinHandle<Result<(File, Bytes), io::Error>>>,
pub(crate) counter: u64,
size: u64,
offset: u64,
state: ChunkedReadFileState,
counter: u64,
}
enum ChunkedReadFileState {
File(Option<File>),
Future(JoinHandle<Result<(File, Bytes), io::Error>>),
}
impl ChunkedReadFile {
pub(crate) fn new(size: u64, offset: u64, file: File) -> Self {
Self {
size,
offset,
state: ChunkedReadFileState::File(Some(file)),
counter: 0,
}
}
}
impl fmt::Debug for ChunkedReadFile {
@ -38,49 +53,52 @@ impl Stream for ChunkedReadFile {
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Self::Item>> {
if let Some(ref mut fut) = self.fut {
let res = match ready!(Pin::new(fut).poll(cx)) {
Ok(Ok((file, bytes))) => {
self.fut.take();
self.file = Some(file);
let this = self.as_mut().get_mut();
match this.state {
ChunkedReadFileState::File(ref mut file) => {
let size = this.size;
let offset = this.offset;
let counter = this.counter;
self.offset += bytes.len() as u64;
self.counter += bytes.len() as u64;
if size == counter {
Poll::Ready(None)
} else {
let mut file = file
.take()
.expect("ChunkedReadFile polled after completion");
Ok(bytes)
let fut = spawn_blocking(move || {
let max_bytes =
cmp::min(size.saturating_sub(counter), 65_536) as usize;
let mut buf = Vec::with_capacity(max_bytes);
file.seek(io::SeekFrom::Start(offset))?;
let n_bytes = file
.by_ref()
.take(max_bytes as u64)
.read_to_end(&mut buf)?;
if n_bytes == 0 {
return Err(io::ErrorKind::UnexpectedEof.into());
}
Ok((file, Bytes::from(buf)))
});
this.state = ChunkedReadFileState::Future(fut);
self.poll_next(cx)
}
Ok(Err(e)) => Err(e.into()),
Err(_) => Err(ErrorInternalServerError("Unexpected error")),
};
return Poll::Ready(Some(res));
}
}
ChunkedReadFileState::Future(ref mut fut) => {
let (file, bytes) =
ready!(Pin::new(fut).poll(cx)).map_err(|_| BlockingError)??;
this.state = ChunkedReadFileState::File(Some(file));
let size = self.size;
let offset = self.offset;
let counter = self.counter;
this.offset += bytes.len() as u64;
this.counter += bytes.len() as u64;
if size == counter {
Poll::Ready(None)
} else {
let mut file = self.file.take().expect("Use after completion");
self.fut = Some(spawn_blocking(move || {
let max_bytes = cmp::min(size.saturating_sub(counter), 65_536) as usize;
let mut buf = Vec::with_capacity(max_bytes);
file.seek(io::SeekFrom::Start(offset))?;
let n_bytes =
file.by_ref().take(max_bytes as u64).read_to_end(&mut buf)?;
if n_bytes == 0 {
return Err(io::ErrorKind::UnexpectedEof.into());
}
Ok((file, Bytes::from(buf)))
}));
self.poll_next(cx)
Poll::Ready(Some(Ok(bytes)))
}
}
}
}

View File

@ -298,13 +298,7 @@ impl NamedFile {
res.encoding(current_encoding);
}
let reader = ChunkedReadFile {
size: self.md.len(),
offset: 0,
file: Some(self.file),
fut: None,
counter: 0,
};
let reader = ChunkedReadFile::new(self.md.len(), 0, self.file);
return res.streaming(reader);
}
@ -426,13 +420,7 @@ impl NamedFile {
return resp.status(StatusCode::NOT_MODIFIED).finish();
}
let reader = ChunkedReadFile {
offset,
size: length,
file: Some(self.file),
fut: None,
counter: 0,
};
let reader = ChunkedReadFile::new(length, offset, self.file);
if offset != 0 || length != self.md.len() {
resp.status(StatusCode::PARTIAL_CONTENT);