Compare commits

...

4 Commits

Author SHA1 Message Date
fasilmveloor a9929b125a
Merge 6eac21683d into e1da110e92 2025-11-14 07:37:40 +09:00
Ruchir e1da110e92
chore: Add public export for `EitherExtractError` (#3826)
* chore: Export EitherExtractError for public use

* refactor: export EitherExtractError
2025-11-11 15:28:40 +00:00
fasilmveloor 6eac21683d
Merge branch 'master' into feat/implement-multipartform-handling-for-optional-vector 2025-02-18 13:26:59 +09:00
fasilmveloor a3e70dcfbc feat: implement FieldGroupReader for Option<Vec<T>> in multipart form handling 2025-02-12 17:54:46 +09:00
4 changed files with 42 additions and 1 deletions

View File

@ -187,6 +187,45 @@ where
} }
} }
impl<'t, T> FieldGroupReader<'t> for Option<Vec<T>>
where
T: FieldReader<'t>,
{
type Future = LocalBoxFuture<'t, Result<(), MultipartError>>;
fn handle_field(
req: &'t HttpRequest,
field: Field,
limits: &'t mut Limits,
state: &'t mut State,
_duplicate_field: DuplicateField,
) -> Self::Future {
let field_name = field.name().unwrap().to_string();
Box::pin(async move {
let vec = state
.entry(field_name)
.or_insert_with(|| Box::<Vec<T>>::default())
.downcast_mut::<Vec<T>>()
.unwrap();
let item = T::read_field(req, field, limits).await?;
vec.push(item);
Ok(())
})
}
fn from_state(name: &str, state: &'t mut State) -> Result<Self, MultipartError> {
if let Some(boxed_vec) = state.remove(name) {
let vec = *boxed_vec.downcast::<Vec<T>>().unwrap();
Ok(Some(vec))
} else {
Ok(None)
}
}
}
/// Trait that allows a type to be used in the [`struct@MultipartForm`] extractor. /// Trait that allows a type to be used in the [`struct@MultipartForm`] extractor.
/// ///
/// You should use the [`macro@MultipartForm`] macro to derive this for your struct. /// You should use the [`macro@MultipartForm`] macro to derive this for your struct.

View File

@ -5,6 +5,7 @@
- `actix_web::response::builder::HttpResponseBuilder::streaming()` now sets `Content-Type` to `application/octet-stream` if `Content-Type` does not exist. - `actix_web::response::builder::HttpResponseBuilder::streaming()` now sets `Content-Type` to `application/octet-stream` if `Content-Type` does not exist.
- `actix_web::response::builder::HttpResponseBuilder::streaming()` now calls `actix_web::response::builder::HttpResponseBuilder::no_chunking()` if `Content-Length` is set by user. - `actix_web::response::builder::HttpResponseBuilder::streaming()` now calls `actix_web::response::builder::HttpResponseBuilder::no_chunking()` if `Content-Length` is set by user.
- Add `ws` crate feature (on-by-default) which forwards to `actix-http` and guards some of its `ResponseError` impls. - Add `ws` crate feature (on-by-default) which forwards to `actix-http` and guards some of its `ResponseError` impls.
- Add public export for `EitherExtractError` in `error` module.
## 4.11.0 ## 4.11.0

View File

@ -21,6 +21,7 @@ mod response_error;
pub(crate) use self::macros::{downcast_dyn, downcast_get_type_id}; pub(crate) use self::macros::{downcast_dyn, downcast_get_type_id};
pub use self::{error::Error, internal::*, response_error::ResponseError}; pub use self::{error::Error, internal::*, response_error::ResponseError};
pub use crate::types::EitherExtractError;
/// A convenience [`Result`](std::result::Result) for Actix Web operations. /// A convenience [`Result`](std::result::Result) for Actix Web operations.
/// ///

View File

@ -11,7 +11,7 @@ mod query;
mod readlines; mod readlines;
pub use self::{ pub use self::{
either::Either, either::{Either, EitherExtractError},
form::{Form, FormConfig, UrlEncoded}, form::{Form, FormConfig, UrlEncoded},
header::Header, header::Header,
html::Html, html::Html,