1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-02 13:29:24 +00: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
* Do not support nested multipart
* Split multipart support to separate crate

View file

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

View file

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

View file

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