1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +01:00

remove nested multipart support

This commit is contained in:
Nikolay Kim 2019-04-13 10:11:07 -07:00
parent 48518df883
commit 043f6e77ae
5 changed files with 45 additions and 89 deletions

View File

@ -2,4 +2,6 @@
## [0.1.0-alpha.1] - 2019-04-xx ## [0.1.0-alpha.1] - 2019-04-xx
* Do not support nested multipart
* Split multipart support to separate crate * Split multipart support to separate crate

View File

@ -16,6 +16,9 @@ pub enum MultipartError {
/// Multipart boundary is not found /// Multipart boundary is not found
#[display(fmt = "Multipart boundary is not found")] #[display(fmt = "Multipart boundary is not found")]
Boundary, Boundary,
/// Nested multipart is not supported
#[display(fmt = "Nested multipart is not supported")]
Nested,
/// Multipart stream is incomplete /// Multipart stream is incomplete
#[display(fmt = "Multipart stream is incomplete")] #[display(fmt = "Multipart stream is incomplete")]
Incomplete, Incomplete,

View File

@ -21,19 +21,13 @@ use crate::server::Multipart;
/// ///
/// fn index(payload: mp::Multipart) -> impl Future<Item = HttpResponse, Error = Error> { /// fn index(payload: mp::Multipart) -> impl Future<Item = HttpResponse, Error = Error> {
/// payload.from_err() // <- get multipart stream for current request /// payload.from_err() // <- get multipart stream for current request
/// .and_then(|item| match item { // <- iterate over multipart items /// .and_then(|field| { // <- iterate over multipart items
/// mp::Item::Field(field) => { /// // Field in turn is stream of *Bytes* object
/// // Field in turn is stream of *Bytes* object /// field.from_err()
/// Either::A(field.from_err() /// .fold((), |_, chunk| {
/// .fold((), |_, chunk| { /// println!("-- CHUNK: \n{:?}", std::str::from_utf8(&chunk));
/// println!("-- CHUNK: \n{:?}", std::str::from_utf8(&chunk)); /// Ok::<_, Error>(())
/// Ok::<_, Error>(()) /// })
/// }))
/// },
/// mp::Item::Nested(mp) => {
/// // Or item could be nested Multipart stream
/// Either::B(ok(()))
/// }
/// }) /// })
/// .fold((), |_, _| Ok::<_, Error>(())) /// .fold((), |_, _| Ok::<_, Error>(()))
/// .map(|_| HttpResponse::Ok().into()) /// .map(|_| HttpResponse::Ok().into())

View File

@ -3,4 +3,4 @@ mod extractor;
mod server; mod server;
pub use self::error::MultipartError; pub use self::error::MultipartError;
pub use self::server::{Field, Item, Multipart}; pub use self::server::{Field, Multipart};

View File

@ -32,18 +32,9 @@ pub struct Multipart {
inner: Option<Rc<RefCell<InnerMultipart>>>, inner: Option<Rc<RefCell<InnerMultipart>>>,
} }
/// Multipart item
pub enum Item {
/// Multipart field
Field(Field),
/// Nested multipart stream
Nested(Multipart),
}
enum InnerMultipartItem { enum InnerMultipartItem {
None, None,
Field(Rc<RefCell<InnerField>>), Field(Rc<RefCell<InnerField>>),
Multipart(Rc<RefCell<InnerMultipart>>),
} }
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@ -113,7 +104,7 @@ impl Multipart {
} }
impl Stream for Multipart { impl Stream for Multipart {
type Item = Item; type Item = Field;
type Error = MultipartError; type Error = MultipartError;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
@ -245,7 +236,7 @@ impl InnerMultipart {
Ok(Some(eof)) Ok(Some(eof))
} }
fn poll(&mut self, safety: &Safety) -> Poll<Option<Item>, MultipartError> { fn poll(&mut self, safety: &Safety) -> Poll<Option<Field>, MultipartError> {
if self.state == InnerState::Eof { if self.state == InnerState::Eof {
Ok(Async::Ready(None)) Ok(Async::Ready(None))
} else { } else {
@ -262,14 +253,7 @@ impl InnerMultipart {
Async::Ready(None) => true, Async::Ready(None) => true,
} }
} }
InnerMultipartItem::Multipart(ref mut multipart) => { InnerMultipartItem::None => false,
match multipart.borrow_mut().poll(safety)? {
Async::NotReady => return Ok(Async::NotReady),
Async::Ready(Some(_)) => continue,
Async::Ready(None) => true,
}
}
_ => false,
}; };
if stop { if stop {
self.item = InnerMultipartItem::None; self.item = InnerMultipartItem::None;
@ -346,24 +330,7 @@ impl InnerMultipart {
// nested multipart stream // nested multipart stream
if mt.type_() == mime::MULTIPART { if mt.type_() == mime::MULTIPART {
let inner = if let Some(boundary) = mt.get_param(mime::BOUNDARY) { Err(MultipartError::Nested)
Rc::new(RefCell::new(InnerMultipart {
payload: self.payload.clone(),
boundary: boundary.as_str().to_owned(),
state: InnerState::FirstBoundary,
item: InnerMultipartItem::None,
}))
} else {
return Err(MultipartError::Boundary);
};
self.item = InnerMultipartItem::Multipart(Rc::clone(&inner));
Ok(Async::Ready(Some(Item::Nested(Multipart {
safety: safety.clone(),
error: None,
inner: Some(inner),
}))))
} else { } else {
let field = Rc::new(RefCell::new(InnerField::new( let field = Rc::new(RefCell::new(InnerField::new(
self.payload.clone(), self.payload.clone(),
@ -372,12 +339,12 @@ impl InnerMultipart {
)?)); )?));
self.item = InnerMultipartItem::Field(Rc::clone(&field)); self.item = InnerMultipartItem::Field(Rc::clone(&field));
Ok(Async::Ready(Some(Item::Field(Field::new( Ok(Async::Ready(Some(Field::new(
safety.clone(), safety.clone(),
headers, headers,
mt, mt,
field, field,
))))) ))))
} }
} }
} }
@ -864,50 +831,40 @@ mod tests {
let mut multipart = Multipart::new(&headers, payload); let mut multipart = Multipart::new(&headers, payload);
match multipart.poll().unwrap() { match multipart.poll().unwrap() {
Async::Ready(Some(item)) => match item { Async::Ready(Some(mut field)) => {
Item::Field(mut field) => { let cd = field.content_disposition().unwrap();
{ assert_eq!(cd.disposition, DispositionType::FormData);
let cd = field.content_disposition().unwrap(); assert_eq!(cd.parameters[0], DispositionParam::Name("file".into()));
assert_eq!(cd.disposition, DispositionType::FormData);
assert_eq!(
cd.parameters[0],
DispositionParam::Name("file".into())
);
}
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.poll().unwrap() { assert_eq!(field.content_type().type_(), mime::TEXT);
Async::Ready(Some(chunk)) => assert_eq!(chunk, "test"), assert_eq!(field.content_type().subtype(), mime::PLAIN);
_ => unreachable!(),
} match field.poll().unwrap() {
match field.poll().unwrap() { Async::Ready(Some(chunk)) => assert_eq!(chunk, "test"),
Async::Ready(None) => (), _ => unreachable!(),
_ => unreachable!(),
}
} }
_ => unreachable!(), match field.poll().unwrap() {
}, Async::Ready(None) => (),
_ => unreachable!(),
}
}
_ => unreachable!(), _ => unreachable!(),
} }
match multipart.poll().unwrap() { match multipart.poll().unwrap() {
Async::Ready(Some(item)) => match item { Async::Ready(Some(mut field)) => {
Item::Field(mut field) => { 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.poll() { match field.poll() {
Ok(Async::Ready(Some(chunk))) => assert_eq!(chunk, "data"), Ok(Async::Ready(Some(chunk))) => assert_eq!(chunk, "data"),
_ => unreachable!(), _ => unreachable!(),
}
match field.poll() {
Ok(Async::Ready(None)) => (),
_ => unreachable!(),
}
} }
_ => unreachable!(), match field.poll() {
}, Ok(Async::Ready(None)) => (),
_ => unreachable!(),
}
}
_ => unreachable!(), _ => unreachable!(),
} }