Update for stable
This commit is contained in:
parent
68c2c45b62
commit
b73b05a663
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "actix-form-data"
|
||||
description = "Multipart Form Data for Actix Web"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
license = "GPL-3.0"
|
||||
authors = ["asonix <asonix.dev@gmail.com>"]
|
||||
repository = "https://github.com/asonix/actix-multipart"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
A library for retrieving form data from Actix Web's multipart streams. It can stream uploaded files
|
||||
onto the filesystem (its main purpose), but it can also parse associated form data.
|
||||
|
||||
[documentation](https://docs.rs/actix-form-data)
|
||||
|
||||
### Usage
|
||||
|
||||
Add it to your dependencies.
|
||||
|
@ -9,7 +11,7 @@ Add it to your dependencies.
|
|||
# Cargo.toml
|
||||
|
||||
[dependencies]
|
||||
actix-form-data = "0.1.0"
|
||||
actix-form-data = "0.1.1"
|
||||
```
|
||||
|
||||
Require it in your project.
|
||||
|
|
|
@ -65,7 +65,7 @@ pub enum Value {
|
|||
impl Value {
|
||||
pub(crate) fn merge(&mut self, rhs: Self) {
|
||||
match (self, rhs) {
|
||||
(Value::Map(ref mut hm), Value::Map(ref other)) => {
|
||||
(&mut Value::Map(ref mut hm), Value::Map(ref other)) => {
|
||||
other.into_iter().fold(hm, |hm, (key, value)| {
|
||||
if hm.contains_key(key) {
|
||||
hm.get_mut(key).unwrap().merge(value.clone())
|
||||
|
@ -76,7 +76,7 @@ impl Value {
|
|||
hm
|
||||
});
|
||||
}
|
||||
(Value::Array(ref mut v), Value::Array(ref other)) => {
|
||||
(&mut Value::Array(ref mut v), Value::Array(ref other)) => {
|
||||
v.extend(other.clone());
|
||||
}
|
||||
_ => (),
|
||||
|
@ -362,8 +362,8 @@ impl Map {
|
|||
Some(name_part) => match name_part {
|
||||
NamePart::Map(part_name) => self.inner
|
||||
.iter()
|
||||
.find(|(item, _)| *item == part_name)
|
||||
.and_then(|(_, field)| field.valid_field(name)),
|
||||
.find(|&&(ref item, _)| *item == part_name)
|
||||
.and_then(|&(_, ref field)| field.valid_field(name)),
|
||||
_ => None,
|
||||
},
|
||||
None => None,
|
||||
|
|
180
src/upload.rs
180
src/upload.rs
|
@ -132,13 +132,13 @@ fn handle_file_upload<S>(
|
|||
gen: Arc<FilenameGenerator>,
|
||||
filename: Option<String>,
|
||||
form: types::Form,
|
||||
) -> impl Future<Item = MultipartContent, Error = Error>
|
||||
) -> Box<Future<Item = MultipartContent, Error = Error>>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
{
|
||||
let filename = match filename {
|
||||
Some(filename) => filename,
|
||||
None => return Either::B(result(Err(Error::Filename))),
|
||||
None => return Box::new(result(Err(Error::Filename))),
|
||||
};
|
||||
|
||||
let path: &Path = filename.as_ref();
|
||||
|
@ -147,12 +147,12 @@ where
|
|||
let filename = if let Some(filename) = filename {
|
||||
filename.to_owned()
|
||||
} else {
|
||||
return Either::B(result(Err(Error::Filename)));
|
||||
return Box::new(result(Err(Error::Filename)));
|
||||
};
|
||||
|
||||
let stored_as = match gen.next_filename(field.content_type()) {
|
||||
Some(file_path) => file_path,
|
||||
None => return Either::B(result(Err(Error::GenFilename))),
|
||||
None => return Box::new(result(Err(Error::GenFilename))),
|
||||
};
|
||||
|
||||
let mut stored_dir = stored_as.clone();
|
||||
|
@ -170,12 +170,12 @@ where
|
|||
tx.send(res).map_err(|_| ())
|
||||
}))) {
|
||||
| Ok(_) => (),
|
||||
Err(_) => return Either::B(result(Err(Error::MkDir))),
|
||||
Err(_) => return Box::new(result(Err(Error::MkDir))),
|
||||
};
|
||||
|
||||
let counter = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
Either::A(rx.then(|res| match res {
|
||||
Box::new(rx.then(|res| match res {
|
||||
Ok(res) => res,
|
||||
Err(_) => Err(Error::MkDir),
|
||||
}).and_then(move |_| {
|
||||
|
@ -204,76 +204,78 @@ fn handle_form_data<S>(
|
|||
field: multipart::Field<S>,
|
||||
term: types::FieldTerminator,
|
||||
form: types::Form,
|
||||
) -> impl Future<Item = MultipartContent, Error = Error>
|
||||
) -> Box<Future<Item = MultipartContent, Error = Error>>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
{
|
||||
trace!("In handle_form_data, term: {:?}", term);
|
||||
let term2 = term.clone();
|
||||
|
||||
field
|
||||
.from_err()
|
||||
.fold(BytesMut::new(), move |mut acc, bytes| {
|
||||
if acc.len() + bytes.len() < form.max_field_size {
|
||||
acc.extend(bytes);
|
||||
Ok(acc)
|
||||
} else {
|
||||
Err(Error::FieldSize)
|
||||
}
|
||||
})
|
||||
.and_then(move |bytes| match term {
|
||||
types::FieldTerminator::Bytes => Ok(MultipartContent::Bytes(bytes.freeze())),
|
||||
_ => String::from_utf8(bytes.to_vec())
|
||||
.map_err(Error::ParseField)
|
||||
.map(MultipartContent::Text),
|
||||
})
|
||||
.and_then(move |content| {
|
||||
trace!("Matching: {:?}", content);
|
||||
match content {
|
||||
types::MultipartContent::Text(string) => match term2 {
|
||||
types::FieldTerminator::File(_) => Err(Error::FieldType),
|
||||
types::FieldTerminator::Bytes => Err(Error::FieldType),
|
||||
types::FieldTerminator::Float => string
|
||||
.parse::<f64>()
|
||||
.map(MultipartContent::Float)
|
||||
.map_err(Error::ParseFloat),
|
||||
types::FieldTerminator::Int => string
|
||||
.parse::<i64>()
|
||||
.map(MultipartContent::Int)
|
||||
.map_err(Error::ParseInt),
|
||||
types::FieldTerminator::Text => Ok(MultipartContent::Text(string)),
|
||||
},
|
||||
b @ types::MultipartContent::Bytes(_) => Ok(b),
|
||||
_ => Err(Error::FieldType),
|
||||
}
|
||||
})
|
||||
Box::new(
|
||||
field
|
||||
.from_err()
|
||||
.fold(BytesMut::new(), move |mut acc, bytes| {
|
||||
if acc.len() + bytes.len() < form.max_field_size {
|
||||
acc.extend(bytes);
|
||||
Ok(acc)
|
||||
} else {
|
||||
Err(Error::FieldSize)
|
||||
}
|
||||
})
|
||||
.and_then(move |bytes| match term {
|
||||
types::FieldTerminator::Bytes => Ok(MultipartContent::Bytes(bytes.freeze())),
|
||||
_ => String::from_utf8(bytes.to_vec())
|
||||
.map_err(Error::ParseField)
|
||||
.map(MultipartContent::Text),
|
||||
})
|
||||
.and_then(move |content| {
|
||||
trace!("Matching: {:?}", content);
|
||||
match content {
|
||||
types::MultipartContent::Text(string) => match term2 {
|
||||
types::FieldTerminator::File(_) => Err(Error::FieldType),
|
||||
types::FieldTerminator::Bytes => Err(Error::FieldType),
|
||||
types::FieldTerminator::Float => string
|
||||
.parse::<f64>()
|
||||
.map(MultipartContent::Float)
|
||||
.map_err(Error::ParseFloat),
|
||||
types::FieldTerminator::Int => string
|
||||
.parse::<i64>()
|
||||
.map(MultipartContent::Int)
|
||||
.map_err(Error::ParseInt),
|
||||
types::FieldTerminator::Text => Ok(MultipartContent::Text(string)),
|
||||
},
|
||||
b @ types::MultipartContent::Bytes(_) => Ok(b),
|
||||
_ => Err(Error::FieldType),
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
fn handle_stream_field<S>(
|
||||
field: multipart::Field<S>,
|
||||
form: types::Form,
|
||||
) -> impl Future<Item = MultipartHash, Error = Error>
|
||||
) -> Box<Future<Item = MultipartHash, Error = Error>>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
{
|
||||
let content_disposition = match parse_content_disposition(&field) {
|
||||
Ok(cd) => cd,
|
||||
Err(e) => return Either::B(result(Err(e))),
|
||||
Err(e) => return Box::new(result(Err(e))),
|
||||
};
|
||||
|
||||
let name = match content_disposition.name {
|
||||
Some(name) => name,
|
||||
None => return Either::B(result(Err(Error::Field))),
|
||||
None => return Box::new(result(Err(Error::Field))),
|
||||
};
|
||||
|
||||
let name = match parse_multipart_name(name) {
|
||||
Ok(name) => name,
|
||||
Err(e) => return Either::B(result(Err(e))),
|
||||
Err(e) => return Box::new(result(Err(e))),
|
||||
};
|
||||
|
||||
let term = match form.valid_field(name.iter().cloned().collect()) {
|
||||
Some(term) => term,
|
||||
None => return Either::B(result(Err(Error::FieldType))),
|
||||
None => return Box::new(result(Err(Error::FieldType))),
|
||||
};
|
||||
|
||||
let fut = match term {
|
||||
|
@ -286,7 +288,7 @@ where
|
|||
term => Either::B(handle_form_data(field, term, form)),
|
||||
};
|
||||
|
||||
Either::A(fut.map(|content| (name, content)))
|
||||
Box::new(fut.map(|content| (name, content)))
|
||||
}
|
||||
|
||||
fn handle_stream<S>(
|
||||
|
@ -321,49 +323,51 @@ where
|
|||
pub fn handle_multipart<S>(
|
||||
m: multipart::Multipart<S>,
|
||||
form: types::Form,
|
||||
) -> impl Future<Item = Value, Error = Error>
|
||||
) -> Box<Future<Item = Value, Error = Error>>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
{
|
||||
handle_stream(m, form.clone())
|
||||
.fold(
|
||||
(Vec::new(), 0, 0),
|
||||
move |(mut acc, file_count, field_count), (name, content)| match content {
|
||||
MultipartContent::File {
|
||||
filename,
|
||||
stored_as,
|
||||
} => {
|
||||
let file_count = file_count + 1;
|
||||
Box::new(
|
||||
handle_stream(m, form.clone())
|
||||
.fold(
|
||||
(Vec::new(), 0, 0),
|
||||
move |(mut acc, file_count, field_count), (name, content)| match content {
|
||||
MultipartContent::File {
|
||||
filename,
|
||||
stored_as,
|
||||
} => {
|
||||
let file_count = file_count + 1;
|
||||
|
||||
if file_count < form.max_files {
|
||||
acc.push((
|
||||
name,
|
||||
MultipartContent::File {
|
||||
filename,
|
||||
stored_as,
|
||||
},
|
||||
));
|
||||
if file_count < form.max_files {
|
||||
acc.push((
|
||||
name,
|
||||
MultipartContent::File {
|
||||
filename,
|
||||
stored_as,
|
||||
},
|
||||
));
|
||||
|
||||
Ok((acc, file_count, field_count))
|
||||
} else {
|
||||
Err(Error::FileCount)
|
||||
Ok((acc, file_count, field_count))
|
||||
} else {
|
||||
Err(Error::FileCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
b @ MultipartContent::Bytes(_)
|
||||
| b @ MultipartContent::Text(_)
|
||||
| b @ MultipartContent::Float(_)
|
||||
| b @ MultipartContent::Int(_) => {
|
||||
let field_count = field_count + 1;
|
||||
b @ MultipartContent::Bytes(_)
|
||||
| b @ MultipartContent::Text(_)
|
||||
| b @ MultipartContent::Float(_)
|
||||
| b @ MultipartContent::Int(_) => {
|
||||
let field_count = field_count + 1;
|
||||
|
||||
if field_count < form.max_fields {
|
||||
acc.push((name, b));
|
||||
if field_count < form.max_fields {
|
||||
acc.push((name, b));
|
||||
|
||||
Ok((acc, file_count, field_count))
|
||||
} else {
|
||||
Err(Error::FieldCount)
|
||||
Ok((acc, file_count, field_count))
|
||||
} else {
|
||||
Err(Error::FieldCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.map(|(multipart_form, _, _)| consolidate(multipart_form))
|
||||
},
|
||||
)
|
||||
.map(|(multipart_form, _, _)| consolidate(multipart_form)),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue