Don't include generic in error type
This commit is contained in:
parent
1e635ce27c
commit
d83b0ad464
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "actix-form-data"
|
||||
description = "Multipart Form Data for Actix Web"
|
||||
version = "0.6.0-beta.8"
|
||||
version = "0.6.0-beta.9"
|
||||
license = "GPL-3.0"
|
||||
authors = ["asonix <asonix@asonix.dog>"]
|
||||
repository = "https://git.asonix.dog/Aardwolf/actix-form-data.git"
|
||||
|
|
|
@ -1,24 +1,10 @@
|
|||
use actix_form_data::{Field, Form, Value};
|
||||
use actix_form_data::{Error, Field, Form, Value};
|
||||
use actix_web::{
|
||||
web::{post, resource},
|
||||
App, HttpResponse, HttpServer, ResponseError,
|
||||
App, HttpResponse, HttpServer,
|
||||
};
|
||||
use futures_util::stream::StreamExt;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("{inner}")]
|
||||
struct MyError {
|
||||
inner: Box<dyn std::error::Error + 'static>,
|
||||
}
|
||||
|
||||
impl MyError {
|
||||
fn new(e: impl std::error::Error + 'static) -> Self {
|
||||
Self { inner: Box::new(e) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for MyError {}
|
||||
|
||||
async fn upload(uploaded_content: Value<()>) -> HttpResponse {
|
||||
println!("Uploaded Content: {:#?}", uploaded_content);
|
||||
HttpResponse::Created().finish()
|
||||
|
@ -39,9 +25,9 @@ async fn main() -> Result<(), anyhow::Error> {
|
|||
"files",
|
||||
Field::array(Field::file(|_, _, mut stream| async move {
|
||||
while let Some(res) = stream.next().await {
|
||||
res.map_err(MyError::new)?;
|
||||
res?;
|
||||
}
|
||||
Ok(()) as Result<(), MyError>
|
||||
Ok(()) as Result<(), Error>
|
||||
})),
|
||||
);
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ async fn upload(uploaded_content: Value<PathBuf>) -> HttpResponse {
|
|||
}
|
||||
|
||||
async fn save_file(
|
||||
stream: Pin<Box<dyn Stream<Item = Result<Bytes, Error<Errors>>>>>,
|
||||
stream: Pin<Box<dyn Stream<Item = Result<Bytes, Error>>>>,
|
||||
count: usize,
|
||||
) -> Result<String, JsonError> {
|
||||
use futures_lite::io::AsyncWriteExt;
|
||||
|
|
13
src/error.rs
13
src/error.rs
|
@ -30,9 +30,7 @@ use actix_web::{
|
|||
};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error<E> {
|
||||
#[error("{0}")]
|
||||
FileFn(E),
|
||||
pub enum Error {
|
||||
#[error("Error parsing payload, {0}")]
|
||||
Payload(#[from] PayloadError),
|
||||
#[error("Error in multipart creation, {0}")]
|
||||
|
@ -63,19 +61,15 @@ pub enum Error<E> {
|
|||
FileSize,
|
||||
}
|
||||
|
||||
impl<E> From<MultipartError> for Error<E> {
|
||||
impl From<MultipartError> for Error {
|
||||
fn from(m: MultipartError) -> Self {
|
||||
Error::Multipart(m)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ResponseError for Error<E>
|
||||
where
|
||||
E: ResponseError,
|
||||
{
|
||||
impl ResponseError for Error {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
Error::FileFn(ref e) => e.status_code(),
|
||||
Error::Payload(ref e) => e.status_code(),
|
||||
_ => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
|
@ -83,7 +77,6 @@ where
|
|||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
match *self {
|
||||
Error::FileFn(ref e) => e.error_response(),
|
||||
Error::Payload(ref e) => e.error_response(),
|
||||
Error::Multipart(_)
|
||||
| Error::ParseField(_)
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
//! while let Some(_) = stream.next().await {
|
||||
//! // do something
|
||||
//! }
|
||||
//! Ok(()) as Result<(), std::io::Error>
|
||||
//! Ok(()) as Result<(), Error>
|
||||
//! })),
|
||||
//! );
|
||||
//!
|
||||
|
|
|
@ -130,7 +130,8 @@ where
|
|||
|
||||
Box::pin(async move {
|
||||
let uploaded = match handle_multipart(multipart, form.clone()).await {
|
||||
Ok(uploaded) => uploaded,
|
||||
Ok(Ok(uploaded)) => uploaded,
|
||||
Ok(Err(e)) => return Err(e.into()),
|
||||
Err(e) => {
|
||||
if let Some(f) = form.transform_error.clone() {
|
||||
return Err((f)(e));
|
||||
|
|
52
src/types.rs
52
src/types.rs
|
@ -157,8 +157,8 @@ pub type FileFn<T, E> = Arc<
|
|||
dyn Fn(
|
||||
String,
|
||||
Mime,
|
||||
Pin<Box<dyn Stream<Item = Result<Bytes, Error<E>>>>>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<T, Error<E>>>>>
|
||||
Pin<Box<dyn Stream<Item = Result<Bytes, Error>>>>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<T, E>>>>
|
||||
+ Send
|
||||
+ Sync,
|
||||
>;
|
||||
|
@ -211,7 +211,7 @@ impl<T, E> Field<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// # use tokio::sync::mpsc::channel;
|
||||
/// # use futures_util::stream::StreamExt;
|
||||
/// #
|
||||
|
@ -226,13 +226,13 @@ impl<T, E> Field<T, E> {
|
|||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// Ok(()) as Result<_, std::io::Error>
|
||||
/// Ok(()) as Result<_, Error>
|
||||
/// }
|
||||
/// }));
|
||||
/// ```
|
||||
pub fn file<F, Fut>(f: F) -> Self
|
||||
where
|
||||
F: Fn(String, Mime, Pin<Box<dyn Stream<Item = Result<Bytes, Error<E>>>>>) -> Fut
|
||||
F: Fn(String, Mime, Pin<Box<dyn Stream<Item = Result<Bytes, Error>>>>) -> Fut
|
||||
+ Send
|
||||
+ Sync
|
||||
+ Clone
|
||||
|
@ -242,7 +242,7 @@ impl<T, E> Field<T, E> {
|
|||
{
|
||||
Field::File(Arc::new(move |filename, mime, stream| {
|
||||
let f = f.clone();
|
||||
Box::pin(async move { (f)(filename, mime, stream).await.map_err(Error::FileFn) })
|
||||
Box::pin(async move { (f)(filename, mime, stream).await })
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -250,8 +250,8 @@ impl<T, E> Field<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// let form = Form::<(), std::io::Error>::new().field("text-field", Field::bytes());
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// let form = Form::<(), Error>::new().field("text-field", Field::bytes());
|
||||
pub fn bytes() -> Self {
|
||||
Field::Bytes
|
||||
}
|
||||
|
@ -260,8 +260,8 @@ impl<T, E> Field<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// let form = Form::<(), std::io::Error>::new().field("text-field", Field::text());
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// let form = Form::<(), Error>::new().field("text-field", Field::text());
|
||||
pub fn text() -> Self {
|
||||
Field::Text
|
||||
}
|
||||
|
@ -270,8 +270,8 @@ impl<T, E> Field<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// let form = Form::<(), std::io::Error>::new().field("int-field", Field::int());
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// let form = Form::<(), Error>::new().field("int-field", Field::int());
|
||||
/// ```
|
||||
pub fn int() -> Self {
|
||||
Field::Int
|
||||
|
@ -281,8 +281,8 @@ impl<T, E> Field<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// let form = Form::<(), std::io::Error>::new().field("float-field", Field::float());
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// let form = Form::<(), Error>::new().field("float-field", Field::float());
|
||||
/// ```
|
||||
pub fn float() -> Self {
|
||||
Field::Float
|
||||
|
@ -292,9 +292,9 @@ impl<T, E> Field<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// # fn main() {
|
||||
/// let form = Form::<(), std::io::Error>::new()
|
||||
/// let form = Form::<(), Error>::new()
|
||||
/// .field(
|
||||
/// "array-field",
|
||||
/// Field::array(Field::text())
|
||||
|
@ -309,9 +309,9 @@ impl<T, E> Field<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// # fn main() {
|
||||
/// let form = Form::<(), std::io::Error>::new()
|
||||
/// let form = Form::<(), Error>::new()
|
||||
/// .field(
|
||||
/// "map-field",
|
||||
/// Field::map()
|
||||
|
@ -434,9 +434,9 @@ impl<T, E> Map<T, E> {
|
|||
/// Add a `Field` to a map
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::Field;
|
||||
/// # use actix_form_data::{Error, Field};
|
||||
/// #
|
||||
/// Field::<(), std::io::Error>::map()
|
||||
/// Field::<(), Error>::map()
|
||||
/// .field("sub-field", Field::text())
|
||||
/// .field("sub-field-two", Field::text())
|
||||
/// .finalize();
|
||||
|
@ -449,9 +449,9 @@ impl<T, E> Map<T, E> {
|
|||
|
||||
/// Finalize the map into a `Field`, so it can be added to a Form
|
||||
/// ```rust
|
||||
/// # use actix_form_data::Field;
|
||||
/// # use actix_form_data::{Error, Field};
|
||||
/// #
|
||||
/// Field::<(), std::io::Error>::map()
|
||||
/// Field::<(), Error>::map()
|
||||
/// .field("sub-field", Field::text())
|
||||
/// .field("sub-field-two", Field::text())
|
||||
/// .finalize();
|
||||
|
@ -477,8 +477,8 @@ impl<T, E> Map<T, E> {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use actix_form_data::{Form, Field};
|
||||
/// let form = Form::<(), std::io::Error>::new()
|
||||
/// # use actix_form_data::{Error, Form, Field};
|
||||
/// let form = Form::<(), Error>::new()
|
||||
/// .field("field-name", Field::text())
|
||||
/// .field("second-field", Field::int())
|
||||
/// .field("third-field", Field::float())
|
||||
|
@ -502,7 +502,7 @@ pub struct Form<T, E> {
|
|||
pub(crate) max_field_size: usize,
|
||||
pub(crate) max_files: u32,
|
||||
pub(crate) max_file_size: usize,
|
||||
pub(crate) transform_error: Option<Arc<dyn Fn(Error<E>) -> actix_web::Error + Send + Sync>>,
|
||||
pub(crate) transform_error: Option<Arc<dyn Fn(Error) -> actix_web::Error + Send + Sync>>,
|
||||
inner: Map<T, E>,
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ impl<T, E> Form<T, E> {
|
|||
/// Set the Transform Error method to convert Error types into actix_web::Error by hand
|
||||
pub fn transform_error(
|
||||
mut self,
|
||||
f: impl Fn(Error<E>) -> actix_web::Error + Send + Sync + 'static,
|
||||
f: impl Fn(Error) -> actix_web::Error + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
self.transform_error = Some(Arc::new(f));
|
||||
self
|
||||
|
|
|
@ -65,7 +65,7 @@ fn consolidate<T>(mf: MultipartForm<T>) -> Value<T> {
|
|||
)
|
||||
}
|
||||
|
||||
fn parse_multipart_name<E>(name: String) -> Result<Vec<NamePart>, Error<E>> {
|
||||
fn parse_multipart_name(name: String) -> Result<Vec<NamePart>, Error> {
|
||||
name.split('[')
|
||||
.map(|part| {
|
||||
if part.len() == 1 && part.ends_with(']') {
|
||||
|
@ -104,7 +104,7 @@ async fn handle_file_upload<T, E>(
|
|||
filename: Option<String>,
|
||||
form: Form<T, E>,
|
||||
file_fn: FileFn<T, E>,
|
||||
) -> Result<MultipartContent<T>, Error<E>>
|
||||
) -> Result<Result<MultipartContent<T>, E>, Error>
|
||||
where
|
||||
T: 'static,
|
||||
E: 'static,
|
||||
|
@ -142,20 +142,23 @@ where
|
|||
}
|
||||
})),
|
||||
)
|
||||
.await?;
|
||||
.await;
|
||||
|
||||
Ok(MultipartContent::File(FileMeta {
|
||||
filename,
|
||||
content_type,
|
||||
result,
|
||||
}))
|
||||
match result {
|
||||
Ok(result) => Ok(Ok(MultipartContent::File(FileMeta {
|
||||
filename,
|
||||
content_type,
|
||||
result,
|
||||
}))),
|
||||
Err(e) => Ok(Err(e)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_form_data<T, E>(
|
||||
mut field: actix_multipart::Field,
|
||||
term: FieldTerminator<T, E>,
|
||||
form: Form<T, E>,
|
||||
) -> Result<MultipartContent<T>, Error<E>>
|
||||
) -> Result<MultipartContent<T>, Error>
|
||||
where
|
||||
T: 'static,
|
||||
E: 'static,
|
||||
|
@ -195,7 +198,7 @@ where
|
|||
async fn handle_stream_field<T, E>(
|
||||
field: actix_multipart::Field,
|
||||
form: Form<T, E>,
|
||||
) -> Result<MultipartHash<T>, Error<E>>
|
||||
) -> Result<Result<MultipartHash<T>, E>, Error>
|
||||
where
|
||||
T: 'static,
|
||||
E: 'static,
|
||||
|
@ -211,19 +214,22 @@ where
|
|||
|
||||
let content = match term {
|
||||
FieldTerminator::File(file_fn) => {
|
||||
handle_file_upload(field, content_disposition.filename, form, file_fn).await?
|
||||
match handle_file_upload(field, content_disposition.filename, form, file_fn).await? {
|
||||
Ok(content) => content,
|
||||
Err(e) => return Ok(Err(e)),
|
||||
}
|
||||
}
|
||||
term => handle_form_data(field, term, form.clone()).await?,
|
||||
};
|
||||
|
||||
Ok((name, content))
|
||||
Ok(Ok((name, content)))
|
||||
}
|
||||
|
||||
/// Handle multipart streams from Actix Web
|
||||
pub async fn handle_multipart<T, E>(
|
||||
m: actix_multipart::Multipart,
|
||||
form: Form<T, E>,
|
||||
) -> Result<Value<T>, Error<E>>
|
||||
) -> Result<Result<Value<T>, E>, Error>
|
||||
where
|
||||
T: 'static,
|
||||
E: 'static,
|
||||
|
@ -245,7 +251,10 @@ where
|
|||
}
|
||||
opt = unordered.next() => {
|
||||
if let Some(res) = opt {
|
||||
let (name_parts, content) = res?;
|
||||
let (name_parts, content) = match res? {
|
||||
Ok(tup) => tup,
|
||||
Err(e) => return Ok(Err(e)),
|
||||
};
|
||||
|
||||
let (l, r) = count(&content, file_count, field_count, &form)?;
|
||||
file_count = l;
|
||||
|
@ -258,7 +267,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
Ok(consolidate(multipart_form))
|
||||
Ok(Ok(consolidate(multipart_form)))
|
||||
}
|
||||
|
||||
fn count<T, E>(
|
||||
|
@ -266,7 +275,7 @@ fn count<T, E>(
|
|||
mut file_count: u32,
|
||||
mut field_count: u32,
|
||||
form: &Form<T, E>,
|
||||
) -> Result<(u32, u32), Error<E>> {
|
||||
) -> Result<(u32, u32), Error> {
|
||||
match content {
|
||||
MultipartContent::File(_) => {
|
||||
file_count += 1;
|
||||
|
|
Loading…
Reference in a new issue