1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-02 21:39:26 +00:00

convert error in Result extractor (#2581)

Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
Ali MJ Al-Nasrawy 2022-01-12 21:59:22 +03:00 committed by GitHub
parent 2a12b41456
commit d90c1a2331
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 16 deletions

View file

@ -7,11 +7,14 @@
### Changed ### Changed
- `HttpResponse` can now be used as a `Responder` with any body type. [#2567] - `HttpResponse` can now be used as a `Responder` with any body type. [#2567]
- `Result` extractor wrapper can now convert error types. [#2581]
- Associated types in `FromRequest` impl for `Option` and `Result` has changed. [#2581]
- Maximim number of extractors has changed from 10 to 12. [#2582] - Maximim number of extractors has changed from 10 to 12. [#2582]
[#1988]: https://github.com/actix/actix-web/pull/1988 [#1988]: https://github.com/actix/actix-web/pull/1988
[#2567]: https://github.com/actix/actix-web/pull/2567 [#2567]: https://github.com/actix/actix-web/pull/2567
[#2569]: https://github.com/actix/actix-web/pull/2569 [#2569]: https://github.com/actix/actix-web/pull/2569
[#2581]: https://github.com/actix/actix-web/pull/2581
[#2582]: https://github.com/actix/actix-web/pull/2582 [#2582]: https://github.com/actix/actix-web/pull/2582

View file

@ -3,6 +3,7 @@
use std::{ use std::{
convert::Infallible, convert::Infallible,
future::Future, future::Future,
marker::PhantomData,
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
}; };
@ -124,12 +125,11 @@ pub trait FromRequest: Sized {
/// ); /// );
/// } /// }
/// ``` /// ```
impl<T: 'static> FromRequest for Option<T> impl<T> FromRequest for Option<T>
where where
T: FromRequest, T: FromRequest,
T::Future: 'static,
{ {
type Error = Error; type Error = Infallible;
type Future = FromRequestOptFuture<T::Future>; type Future = FromRequestOptFuture<T::Future>;
#[inline] #[inline]
@ -152,7 +152,7 @@ where
Fut: Future<Output = Result<T, E>>, Fut: Future<Output = Result<T, E>>,
E: Into<Error>, E: Into<Error>,
{ {
type Output = Result<Option<T>, Error>; type Output = Result<Option<T>, Infallible>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();
@ -211,40 +211,42 @@ where
/// ); /// );
/// } /// }
/// ``` /// ```
impl<T> FromRequest for Result<T, T::Error> impl<T, E> FromRequest for Result<T, E>
where where
T: FromRequest + 'static, T: FromRequest,
T::Error: 'static, T::Error: Into<E>,
T::Future: 'static,
{ {
type Error = Error; type Error = Infallible;
type Future = FromRequestResFuture<T::Future>; type Future = FromRequestResFuture<T::Future, E>;
#[inline] #[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
FromRequestResFuture { FromRequestResFuture {
fut: T::from_request(req, payload), fut: T::from_request(req, payload),
_phantom: PhantomData,
} }
} }
} }
pin_project! { pin_project! {
pub struct FromRequestResFuture<Fut> { pub struct FromRequestResFuture<Fut, E> {
#[pin] #[pin]
fut: Fut, fut: Fut,
_phantom: PhantomData<E>,
} }
} }
impl<Fut, T, E> Future for FromRequestResFuture<Fut> impl<Fut, T, Ei, E> Future for FromRequestResFuture<Fut, E>
where where
Fut: Future<Output = Result<T, E>>, Fut: Future<Output = Result<T, Ei>>,
Ei: Into<E>,
{ {
type Output = Result<Result<T, E>, Error>; type Output = Result<Result<T, E>, Infallible>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();
let res = ready!(this.fut.poll(cx)); let res = ready!(this.fut.poll(cx));
Poll::Ready(Ok(res)) Poll::Ready(Ok(res.map_err(Into::into)))
} }
} }
@ -481,7 +483,14 @@ mod tests {
.set_payload(Bytes::from_static(b"bye=world")) .set_payload(Bytes::from_static(b"bye=world"))
.to_http_parts(); .to_http_parts();
let r = Result::<Form<Info>, Error>::from_request(&req, &mut pl) struct MyError;
impl From<Error> for MyError {
fn from(_: Error) -> Self {
Self
}
}
let r = Result::<Form<Info>, MyError>::from_request(&req, &mut pl)
.await .await
.unwrap(); .unwrap();
assert!(r.is_err()); assert!(r.is_err());