Skip to content

Commit 7be661f

Browse files
committed
feat: use PRITIT for FromRequest
1 parent f565572 commit 7be661f

File tree

16 files changed

+159
-458
lines changed

16 files changed

+159
-458
lines changed

actix-files/src/path_buf.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::{
33
str::FromStr,
44
};
55

6-
use actix_utils::future::{ready, Ready};
76
use actix_web::{dev::Payload, FromRequest, HttpRequest};
87

98
use crate::error::UriSegmentError;
@@ -88,10 +87,10 @@ impl AsRef<Path> for PathBufWrap {
8887

8988
impl FromRequest for PathBufWrap {
9089
type Error = UriSegmentError;
91-
type Future = Ready<Result<Self, Self::Error>>;
9290

93-
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
94-
ready(req.match_info().unprocessed().parse())
91+
#[inline]
92+
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
93+
req.match_info().unprocessed().parse()
9594
}
9695
}
9796

actix-web/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ serde_json = "1.0"
100100
serde_urlencoded = "0.7"
101101
smallvec = "1.6.1"
102102
socket2 = "0.5"
103+
tokio = { version = "1.24.2", features = ["macros"] }
103104
time = { version = "0.3", default-features = false, features = ["formatting"] }
104105
url = "2.1"
105106

actix-web/src/data.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::{any::type_name, ops::Deref, sync::Arc};
22

33
use actix_http::Extensions;
4-
use actix_utils::future::{err, ok, Ready};
54
use futures_core::future::LocalBoxFuture;
65
use serde::{de, Serialize};
76

@@ -159,12 +158,11 @@ where
159158

160159
impl<T: ?Sized + 'static> FromRequest for Data<T> {
161160
type Error = Error;
162-
type Future = Ready<Result<Self, Error>>;
163161

164162
#[inline]
165-
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
163+
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
166164
if let Some(st) = req.app_data::<Data<T>>() {
167-
ok(st.clone())
165+
Ok(st.clone())
168166
} else {
169167
log::debug!(
170168
"Failed to extract `Data<{}>` for `{}` handler. For the Data extractor to work \
@@ -174,7 +172,7 @@ impl<T: ?Sized + 'static> FromRequest for Data<T> {
174172
req.match_name().unwrap_or_else(|| req.path())
175173
);
176174

177-
err(error::ErrorInternalServerError(
175+
Err(error::ErrorInternalServerError(
178176
"Requested application data is not configured correctly. \
179177
View/enable debug logs for more details.",
180178
))

actix-web/src/extract.rs

Lines changed: 34 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
use std::{
44
convert::Infallible,
55
future::Future,
6-
marker::PhantomData,
76
pin::Pin,
87
task::{Context, Poll},
98
};
109

1110
use actix_http::{Method, Uri};
12-
use actix_utils::future::{ok, Ready};
1311
use futures_core::ready;
1412
use pin_project_lite::pin_project;
1513

@@ -66,33 +64,17 @@ pub trait FromRequest: Sized {
6664
/// The associated error which can be returned.
6765
type Error: Into<Error>;
6866

69-
/// Future that resolves to a `Self`.
70-
///
71-
/// To use an async function or block, the futures must be boxed. The following snippet will be
72-
/// common when creating async/await extractors (that do not consume the body).
73-
///
74-
/// ```ignore
75-
/// type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
76-
/// // or
77-
/// type Future = futures_util::future::LocalBoxFuture<'static, Result<Self, Self::Error>>;
78-
///
79-
/// fn from_request(req: HttpRequest, ...) -> Self::Future {
80-
/// let req = req.clone();
81-
/// Box::pin(async move {
82-
/// ...
83-
/// })
84-
/// }
85-
/// ```
86-
type Future: Future<Output = Result<Self, Self::Error>>;
87-
88-
/// Create a `Self` from request parts asynchronously.
89-
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future;
67+
/// Creates a `Self` from request parts asynchronously.
68+
fn from_request(
69+
req: &HttpRequest,
70+
payload: &mut Payload,
71+
) -> impl Future<Output = Result<Self, Self::Error>>;
9072

9173
/// Create a `Self` from request head asynchronously.
9274
///
9375
/// This method is short for `T::from_request(req, &mut Payload::None)`.
94-
fn extract(req: &HttpRequest) -> Self::Future {
95-
Self::from_request(req, &mut Payload::None)
76+
fn extract(req: &HttpRequest) -> impl Future<Output = Result<Self, Self::Error>> {
77+
async { Self::from_request(req, &mut Payload::None).await }
9678
}
9779
}
9880

@@ -146,12 +128,19 @@ where
146128
T: FromRequest,
147129
{
148130
type Error = Infallible;
149-
type Future = FromRequestOptFuture<T::Future>;
150131

151132
#[inline]
152-
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
153-
FromRequestOptFuture {
154-
fut: T::from_request(req, payload),
133+
async fn from_request(req: &HttpRequest, payload: &mut Payload) -> Result<Self, Self::Error> {
134+
match T::from_request(req, payload).await {
135+
Ok(t) => Ok(Some(t)),
136+
Err(err) => {
137+
log::debug!(
138+
"Error from `Option<{}>` extractor: {}",
139+
std::any::type_name::<T>(),
140+
err.into()
141+
);
142+
Ok(None)
143+
}
155144
}
156145
}
157146
}
@@ -203,9 +192,11 @@ where
203192
///
204193
/// impl FromRequest for Thing {
205194
/// type Error = Error;
206-
/// type Future = Ready<Result<Thing, Error>>;
207195
///
208-
/// fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future {
196+
/// async fn from_request(
197+
/// req: &HttpRequest,
198+
/// payload: &mut dev::Payload,
199+
/// ) -> Result<Self, Self::Error> {
209200
/// if rand::random() {
210201
/// ok(Thing { name: "thingy".into() })
211202
/// } else {
@@ -232,36 +223,10 @@ where
232223
T::Error: Into<E>,
233224
{
234225
type Error = Infallible;
235-
type Future = FromRequestResFuture<T::Future, E>;
236226

237227
#[inline]
238-
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
239-
FromRequestResFuture {
240-
fut: T::from_request(req, payload),
241-
_phantom: PhantomData,
242-
}
243-
}
244-
}
245-
246-
pin_project! {
247-
pub struct FromRequestResFuture<Fut, E> {
248-
#[pin]
249-
fut: Fut,
250-
_phantom: PhantomData<E>,
251-
}
252-
}
253-
254-
impl<Fut, T, Ei, E> Future for FromRequestResFuture<Fut, E>
255-
where
256-
Fut: Future<Output = Result<T, Ei>>,
257-
Ei: Into<E>,
258-
{
259-
type Output = Result<Result<T, E>, Infallible>;
260-
261-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
262-
let this = self.project();
263-
let res = ready!(this.fut.poll(cx));
264-
Poll::Ready(Ok(res.map_err(Into::into)))
228+
async fn from_request(req: &HttpRequest, payload: &mut Payload) -> Result<Self, Self::Error> {
229+
Ok(T::from_request(req, payload).await.map_err(Into::into))
265230
}
266231
}
267232

@@ -279,10 +244,9 @@ where
279244
/// ```
280245
impl FromRequest for Uri {
281246
type Error = Infallible;
282-
type Future = Ready<Result<Self, Self::Error>>;
283247

284-
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
285-
ok(req.uri().clone())
248+
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
249+
Ok(req.uri().clone())
286250
}
287251
}
288252

@@ -300,10 +264,9 @@ impl FromRequest for Uri {
300264
/// ```
301265
impl FromRequest for Method {
302266
type Error = Infallible;
303-
type Future = Ready<Result<Self, Self::Error>>;
304267

305-
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
306-
ok(req.method().clone())
268+
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
269+
Ok(req.method().clone())
307270
}
308271
}
309272

@@ -319,88 +282,24 @@ mod tuple_from_req {
319282
impl<$($T: FromRequest + 'static),+> FromRequest for ($($T,)+)
320283
{
321284
type Error = Error;
322-
type Future = $fut<$($T),+>;
323-
324-
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
325-
$fut {
326-
$(
327-
$T: ExtractFuture::Future {
328-
fut: $T::from_request(req, payload)
329-
},
330-
)+
331-
}
332-
}
333-
}
334285

335-
pin_project! {
336-
pub struct $fut<$($T: FromRequest),+> {
286+
async fn from_request(req: &HttpRequest, payload: &mut Payload) -> Result<Self, Self::Error> {
337287
$(
338-
#[pin]
339-
$T: ExtractFuture<$T::Future, $T>,
288+
let $T = $T::from_request(req, payload).await.map_err(Into::into)?;
340289
)+
341-
}
342-
}
343290

344-
impl<$($T: FromRequest),+> Future for $fut<$($T),+>
345-
{
346-
type Output = Result<($($T,)+), Error>;
347-
348-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
349-
let mut this = self.project();
350-
351-
let mut ready = true;
352-
$(
353-
match this.$T.as_mut().project() {
354-
ExtractProj::Future { fut } => match fut.poll(cx) {
355-
Poll::Ready(Ok(output)) => {
356-
let _ = this.$T.as_mut().project_replace(ExtractFuture::Done { output });
357-
},
358-
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
359-
Poll::Pending => ready = false,
360-
},
361-
ExtractProj::Done { .. } => {},
362-
ExtractProj::Empty => unreachable!("FromRequest polled after finished"),
363-
}
364-
)+
365-
366-
if ready {
367-
Poll::Ready(Ok(
368-
($(
369-
match this.$T.project_replace(ExtractFuture::Empty) {
370-
ExtractReplaceProj::Done { output } => output,
371-
_ => unreachable!("FromRequest polled after finished"),
372-
},
373-
)+)
374-
))
375-
} else {
376-
Poll::Pending
377-
}
291+
Ok(($($T,)+))
378292
}
379293
}
380294
};
381295
}
382296

383-
pin_project! {
384-
#[project = ExtractProj]
385-
#[project_replace = ExtractReplaceProj]
386-
enum ExtractFuture<Fut, Res> {
387-
Future {
388-
#[pin]
389-
fut: Fut
390-
},
391-
Done {
392-
output: Res,
393-
},
394-
Empty
395-
}
396-
}
397-
398297
impl FromRequest for () {
399298
type Error = Infallible;
400-
type Future = Ready<Result<Self, Self::Error>>;
401299

402-
fn from_request(_: &HttpRequest, _: &mut Payload) -> Self::Future {
403-
ok(())
300+
#[inline]
301+
async fn from_request(_: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
302+
Ok(())
404303
}
405304
}
406305

actix-web/src/info.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{convert::Infallible, net::SocketAddr};
22

3-
use actix_utils::future::{err, ok, Ready};
43
use derive_more::{Display, Error};
54

65
use crate::{
@@ -198,10 +197,10 @@ impl ConnectionInfo {
198197

199198
impl FromRequest for ConnectionInfo {
200199
type Error = Infallible;
201-
type Future = Ready<Result<Self, Self::Error>>;
202200

203-
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
204-
ok(req.connection_info().clone())
201+
#[inline]
202+
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
203+
Ok(req.connection_info().clone())
205204
}
206205
}
207206

@@ -240,14 +239,14 @@ impl ResponseError for MissingPeerAddr {}
240239

241240
impl FromRequest for PeerAddr {
242241
type Error = MissingPeerAddr;
243-
type Future = Ready<Result<Self, Self::Error>>;
244242

245-
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
243+
#[inline]
244+
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
246245
match req.peer_addr() {
247-
Some(addr) => ok(PeerAddr(addr)),
246+
Some(addr) => Ok(PeerAddr(addr)),
248247
None => {
249248
log::error!("Missing peer address.");
250-
err(MissingPeerAddr)
249+
Err(MissingPeerAddr)
251250
}
252251
}
253252
}

actix-web/src/request.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::{
22
cell::{Ref, RefCell, RefMut},
3+
convert::Infallible,
34
fmt, net,
45
rc::Rc,
56
str,
67
};
78

89
use actix_http::{Message, RequestHead};
910
use actix_router::{Path, Url};
10-
use actix_utils::future::{ok, Ready};
1111
#[cfg(feature = "cookies")]
1212
use cookie::{Cookie, ParseError as CookieParseError};
1313
use smallvec::SmallVec;
@@ -20,7 +20,7 @@ use crate::{
2020
http::{header::HeaderMap, Method, Uri, Version},
2121
info::ConnectionInfo,
2222
rmap::ResourceMap,
23-
Error, FromRequest, HttpMessage,
23+
FromRequest, HttpMessage,
2424
};
2525

2626
#[cfg(feature = "cookies")]
@@ -417,12 +417,11 @@ impl Drop for HttpRequest {
417417
/// );
418418
/// ```
419419
impl FromRequest for HttpRequest {
420-
type Error = Error;
421-
type Future = Ready<Result<Self, Error>>;
420+
type Error = Infallible;
422421

423422
#[inline]
424-
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
425-
ok(req.clone())
423+
async fn from_request(req: &HttpRequest, _: &mut Payload) -> Result<Self, Self::Error> {
424+
Ok(req.clone())
426425
}
427426
}
428427

0 commit comments

Comments
 (0)