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:
parent
48518df883
commit
043f6e77ae
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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())
|
||||||
|
@ -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};
|
||||||
|
@ -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!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user