Merge branch 'master' into patch-1

This commit is contained in:
Nikolay Kim 2019-12-12 07:06:11 +06:00 committed by GitHub
commit be9005cf37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 25 deletions

View File

@ -274,10 +274,14 @@ impl Files {
/// By default pool with 5x threads of available cpus is used. /// By default pool with 5x threads of available cpus is used.
/// Pool size can be changed by setting ACTIX_CPU_POOL environment variable. /// Pool size can be changed by setting ACTIX_CPU_POOL environment variable.
pub fn new<T: Into<PathBuf>>(path: &str, dir: T) -> Files { pub fn new<T: Into<PathBuf>>(path: &str, dir: T) -> Files {
let dir = dir.into().canonicalize().unwrap_or_else(|_| PathBuf::new()); let orig_dir = dir.into();
if !dir.is_dir() { let dir = match orig_dir.canonicalize() {
log::error!("Specified path is not a directory: {:?}", dir); Ok(canon_dir) => canon_dir,
Err(_) => {
log::error!("Specified path is not a directory: {:?}", orig_dir);
PathBuf::new()
} }
};
Files { Files {
path: path.to_string(), path: path.to_string(),

View File

@ -109,7 +109,7 @@ impl fmt::Display for Error {
impl fmt::Debug for Error { impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "{:?}", &self.cause) write!(f, "{:?}", &self.cause)
} }
} }

View File

@ -1,5 +1,9 @@
# Changes # Changes
## [2.0.0-alpha.4] - 2019-12-xx
* Multipart handling now handles Pending during read of boundary #1205
## [0.2.0-alpha.2] - 2019-12-03 ## [0.2.0-alpha.2] - 2019-12-03
* Migrate to `std::future` * Migrate to `std::future`

View File

@ -610,7 +610,7 @@ impl InnerField {
} }
match payload.readline() { match payload.readline() {
Ok(None) => Poll::Ready(None), Ok(None) => Poll::Pending,
Ok(Some(line)) => { Ok(Some(line)) => {
if line.as_ref() != b"\r\n" { if line.as_ref() != b"\r\n" {
log::warn!("multipart field did not read all the data or it is malformed"); log::warn!("multipart field did not read all the data or it is malformed");
@ -867,6 +867,42 @@ mod tests {
(tx, rx.map(|res| res.map_err(|_| panic!()))) (tx, rx.map(|res| res.map_err(|_| panic!())))
} }
// Stream that returns from a Bytes, one char at a time and Pending every other poll()
struct SlowStream {
bytes: Bytes,
pos: usize,
ready: bool,
}
impl SlowStream {
fn new(bytes: Bytes) -> SlowStream {
return SlowStream {
bytes: bytes,
pos: 0,
ready: false,
}
}
}
impl Stream for SlowStream {
type Item = Result<Bytes, PayloadError>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
if !this.ready {
this.ready = true;
cx.waker().wake_by_ref();
return Poll::Pending;
}
if this.pos == this.bytes.len() {
return Poll::Ready(None);
}
let res = Poll::Ready(Some(Ok(this.bytes.slice(this.pos..(this.pos + 1)))));
this.pos += 1;
this.ready = false;
res
}
}
fn create_simple_request_with_header() -> (Bytes, HeaderMap) { fn create_simple_request_with_header() -> (Bytes, HeaderMap) {
let bytes = Bytes::from( let bytes = Bytes::from(
@ -969,12 +1005,22 @@ mod tests {
} }
} }
// Loops, collecting all bytes until end-of-field
async fn get_whole_field(field: &mut Field) -> BytesMut {
let mut b = BytesMut::new();
loop {
match field.next().await {
Some(Ok(chunk)) => b.extend_from_slice(&chunk),
None => return b,
_ => unreachable!(),
}
}
}
#[actix_rt::test] #[actix_rt::test]
async fn test_stream() { async fn test_stream() {
let (sender, payload) = create_stream();
let (bytes, headers) = create_simple_request_with_header(); let (bytes, headers) = create_simple_request_with_header();
let payload = SlowStream::new(bytes);
sender.send(Ok(bytes)).unwrap();
let mut multipart = Multipart::new(&headers, payload); let mut multipart = Multipart::new(&headers, payload);
match multipart.next().await.unwrap() { match multipart.next().await.unwrap() {
@ -986,14 +1032,7 @@ mod tests {
assert_eq!(field.content_type().type_(), mime::TEXT); assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN); assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await.unwrap() { assert_eq!(get_whole_field(&mut field).await, "test");
Ok(chunk) => assert_eq!(chunk, "test"),
_ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
} }
_ => unreachable!(), _ => unreachable!(),
} }
@ -1003,14 +1042,7 @@ mod tests {
assert_eq!(field.content_type().type_(), mime::TEXT); assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN); assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await { assert_eq!(get_whole_field(&mut field).await, "data");
Some(Ok(chunk)) => assert_eq!(chunk, "data"),
_ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
} }
_ => unreachable!(), _ => unreachable!(),
} }