mirror of
https://github.com/actix/actix-web.git
synced 2025-01-24 16:08:06 +00:00
convert error in Result
extractor (#2581)
Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
parent
2a12b41456
commit
d90c1a2331
2 changed files with 28 additions and 16 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in a new issue