keep future impl for response

This commit is contained in:
Rob Ede 2021-05-07 11:59:46 +01:00
parent 310506b257
commit 274a3a9c07
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
8 changed files with 75 additions and 66 deletions

View File

@ -9,6 +9,7 @@
### Changed ### Changed
* The `MessageBody` trait now has an associated `Error` type. [#2183] * The `MessageBody` trait now has an associated `Error` type. [#2183]
* Places in `Response` where `ResponseBody<B>` was received or returned now simply use `B`. [#2201]
* `header` mod is now public. [#2171] * `header` mod is now public. [#2171]
* `uri` mod is now public. [#2171] * `uri` mod is now public. [#2171]
* Update `language-tags` to `0.3`. * Update `language-tags` to `0.3`.
@ -17,12 +18,12 @@
### Removed ### Removed
* Stop re-exporting `http` crate's `HeaderMap` types in addition to ours. [#2171] * Stop re-exporting `http` crate's `HeaderMap` types in addition to ours. [#2171]
* Down-casting for `MessageBody` types. [#2183] * Down-casting for `MessageBody` types. [#2183]
* `error::Result` alias. [#????] * `error::Result` alias. [#2201]
[#2171]: https://github.com/actix/actix-web/pull/2171 [#2171]: https://github.com/actix/actix-web/pull/2171
[#2183]: https://github.com/actix/actix-web/pull/2183 [#2183]: https://github.com/actix/actix-web/pull/2183
[#2196]: https://github.com/actix/actix-web/pull/2196 [#2196]: https://github.com/actix/actix-web/pull/2196
[#????]: https://github.com/actix/actix-web/pull/???? [#2201]: https://github.com/actix/actix-web/pull/2201
## 3.0.0-beta.6 - 2021-04-17 ## 3.0.0-beta.6 - 2021-04-17

View File

@ -346,7 +346,7 @@ where
ServiceResponseStateProj::SendErrorPayload(ref mut stream, ref mut body) => { ServiceResponseStateProj::SendErrorPayload(ref mut stream, ref mut body) => {
// TODO: de-dupe impl with SendPayload // TODO: de-dupe impl with SendPayload
loop { loop {
match this.buffer { match this.buffer {
Some(ref mut buffer) => match ready!(stream.poll_capacity(cx)) { Some(ref mut buffer) => match ready!(stream.poll_capacity(cx)) {

View File

@ -389,6 +389,14 @@ impl BoxedResponseHead {
pub fn new(status: StatusCode) -> Self { pub fn new(status: StatusCode) -> Self {
RESPONSE_POOL.with(|p| p.get_message(status)) RESPONSE_POOL.with(|p| p.get_message(status))
} }
// used in: impl Future for Response
#[allow(dead_code)]
pub(crate) fn take(&mut self) -> Self {
BoxedResponseHead {
head: self.head.take(),
}
}
} }
impl std::ops::Deref for BoxedResponseHead { impl std::ops::Deref for BoxedResponseHead {

View File

@ -19,7 +19,7 @@ use crate::{
/// An HTTP response. /// An HTTP response.
pub struct Response<B> { pub struct Response<B> {
pub(crate) head: BoxedResponseHead, pub(crate) head: BoxedResponseHead,
pub(crate) body: B, pub(crate) body: Option<B>,
pub(crate) error: Option<Error>, pub(crate) error: Option<Error>,
} }
@ -29,7 +29,7 @@ impl Response<Body> {
pub fn new(status: StatusCode) -> Response<Body> { pub fn new(status: StatusCode) -> Response<Body> {
Response { Response {
head: BoxedResponseHead::new(status), head: BoxedResponseHead::new(status),
body: Body::Empty, body: Some(Body::Empty),
error: None, error: None,
} }
} }
@ -79,19 +79,6 @@ impl Response<Body> {
resp.error = Some(error); resp.error = Some(error);
resp resp
} }
// /// Convert response to response with body
// pub fn into_body<B>(self) -> Response<B> {
// let b = match self.body {
// ResponseBody::Body(b) => b,
// ResponseBody::Other(b) => b,
// };
// Response {
// head: self.head,
// error: self.error,
// body: ResponseBody::Other(b),
// }
// }
} }
impl<B> Response<B> { impl<B> Response<B> {
@ -100,7 +87,7 @@ impl<B> Response<B> {
pub fn with_body(status: StatusCode, body: B) -> Response<B> { pub fn with_body(status: StatusCode, body: B) -> Response<B> {
Response { Response {
head: BoxedResponseHead::new(status), head: BoxedResponseHead::new(status),
body, body: Some(body),
error: None, error: None,
} }
} }
@ -173,14 +160,14 @@ impl<B> Response<B> {
/// Get body of this response /// Get body of this response
#[inline] #[inline]
pub fn body(&self) -> &B { pub fn body(&self) -> &B {
&self.body self.body.as_ref().unwrap()
} }
/// Set a body /// Set a body
pub fn set_body<B2>(self, body: B2) -> Response<B2> { pub fn set_body<B2>(self, body: B2) -> Response<B2> {
Response { Response {
head: self.head, head: self.head,
body, body: Some(body),
error: None, error: None,
} }
} }
@ -190,10 +177,10 @@ impl<B> Response<B> {
( (
Response { Response {
head: self.head, head: self.head,
body: (), body: Some(()),
error: self.error, error: self.error,
}, },
self.body, self.body.unwrap(),
) )
} }
@ -201,7 +188,7 @@ impl<B> Response<B> {
pub fn drop_body(self) -> Response<()> { pub fn drop_body(self) -> Response<()> {
Response { Response {
head: self.head, head: self.head,
body: (), body: Some(()),
error: None, error: None,
} }
} }
@ -211,10 +198,10 @@ impl<B> Response<B> {
( (
Response { Response {
head: self.head, head: self.head,
body, body: Some(body),
error: self.error, error: self.error,
}, },
self.body, self.body.unwrap(),
) )
} }
@ -223,11 +210,11 @@ impl<B> Response<B> {
where where
F: FnOnce(&mut ResponseHead, B) -> B2, F: FnOnce(&mut ResponseHead, B) -> B2,
{ {
let body = f(&mut self.head, self.body); let body = f(&mut self.head, self.body.unwrap());
Response { Response {
body,
head: self.head, head: self.head,
body: Some(body),
error: self.error, error: self.error,
} }
} }
@ -239,7 +226,7 @@ impl<B> Response<B> {
/// Extract response body /// Extract response body
pub fn into_body(self) -> B { pub fn into_body(self) -> B {
self.body self.body.unwrap()
} }
} }
@ -260,23 +247,41 @@ where
for (key, val) in self.head.headers.iter() { for (key, val) in self.head.headers.iter() {
let _ = writeln!(f, " {:?}: {:?}", key, val); let _ = writeln!(f, " {:?}: {:?}", key, val);
} }
let _ = writeln!(f, " body: {:?}", self.body.size()); let _ = writeln!(f, " body: {:?}", self.body.as_ref().unwrap().size());
res res
} }
} }
// TODO: document why this is needed impl<B: Default> Default for Response<B> {
// impl<B: Unpin> Future for Response<B> { #[inline]
// type Output = Result<Response<B>, Infallible>; fn default() -> Response<B> {
Response::with_body(StatusCode::default(), B::default())
}
}
// fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { mod fut {
// Poll::Ready(Ok(Response { use std::{
// head: self.head.take(), convert::Infallible,
// body: self.body.take_body(), future::Future,
// error: self.error.take(), pin::Pin,
// })) task::{Context, Poll},
// } };
// }
use super::*;
// TODO: document why this is needed
impl<B: Unpin> Future for Response<B> {
type Output = Result<Response<B>, Infallible>;
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Ready(Ok(Response {
head: self.head.take(),
body: self.body.take(),
error: self.error.take(),
}))
}
}
}
/// Helper converters /// Helper converters
impl<I: Into<Response<Body>>, E: Into<Error>> From<Result<I, E>> for Response<Body> { impl<I: Into<Response<Body>>, E: Into<Error>> From<Result<I, E>> for Response<Body> {

View File

@ -251,7 +251,7 @@ impl ResponseBuilder {
Response { Response {
head: response, head: response,
body, body: Some(body),
error: None, error: None,
} }
} }

View File

@ -2,7 +2,6 @@ use std::{
cell::{Ref, RefMut}, cell::{Ref, RefMut},
fmt, fmt,
future::Future, future::Future,
mem,
pin::Pin, pin::Pin,
task::{Context, Poll}, task::{Context, Poll},
}; };
@ -12,6 +11,7 @@ use actix_http::{
http::{header::HeaderMap, StatusCode}, http::{header::HeaderMap, StatusCode},
Extensions, Response, ResponseHead, Extensions, Response, ResponseHead,
}; };
use futures_core::ready;
#[cfg(feature = "cookies")] #[cfg(feature = "cookies")]
use { use {
@ -56,14 +56,6 @@ impl HttpResponse<Body> {
error: Some(error), error: Some(error),
} }
} }
// /// Convert response to response with body
// pub fn into_body<B>(self) -> HttpResponse<B> {
// HttpResponse {
// res: self.res.into_body(),
// error: self.error,
// }
// }
} }
impl<B> HttpResponse<B> { impl<B> HttpResponse<B> {
@ -241,7 +233,7 @@ impl<B> HttpResponse<B> {
// pub fn take_body(&mut self) -> ResponseBody<B> { // pub fn take_body(&mut self) -> ResponseBody<B> {
// self.res.take_body() // self.res.take_body()
// } // }
/// Extract response body /// Extract response body
pub fn into_body(self) -> B { pub fn into_body(self) -> B {
self.res.into_body() self.res.into_body()
@ -279,26 +271,28 @@ impl<B> From<HttpResponse<B>> for Response<B> {
// TODO: expose cause somewhere? // TODO: expose cause somewhere?
// if let Some(err) = res.error { // if let Some(err) = res.error {
// eprintln!("impl<B> From<HttpResponse<B>> for Response<B> let Some(err)"); // return Response::from_error(err);
// return Response::from_error(err).into_body();
// } // }
res.res res.res
} }
} }
impl Future for HttpResponse { impl<B: Unpin> Future for HttpResponse<B> {
type Output = Result<Response<Body>, Error>; type Output = Result<Response<B>, Error>;
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// if let Some(err) = self.error.take() { if let Some(err) = self.error.take() {
// return Poll::Ready(Ok(Response::from_error(err).into_body())); return Poll::Ready(Err(err));
// } }
Poll::Ready(Ok(mem::replace( let res = &mut self.res;
&mut self.res, actix_rt::pin!(res);
Response::new(StatusCode::default()),
))) match ready!(res.poll(cx)) {
Ok(val) => Poll::Ready(Ok(val)),
Err(err) => Poll::Ready(Err(err.into())),
}
} }
} }

View File

@ -578,7 +578,7 @@ mod tests {
use actix_utils::future::ok; use actix_utils::future::ok;
use bytes::Bytes; use bytes::Bytes;
use crate::dev::{Body}; use crate::dev::Body;
use crate::http::{header, HeaderValue, Method, StatusCode}; use crate::http::{header, HeaderValue, Method, StatusCode};
use crate::middleware::DefaultHeaders; use crate::middleware::DefaultHeaders;
use crate::service::ServiceRequest; use crate::service::ServiceRequest;

View File

@ -4,9 +4,10 @@ use std::{net::SocketAddr, rc::Rc};
pub use actix_http::test::TestBuffer; pub use actix_http::test::TestBuffer;
use actix_http::{ use actix_http::{
body,
http::{header::IntoHeaderPair, Method, StatusCode, Uri, Version}, http::{header::IntoHeaderPair, Method, StatusCode, Uri, Version},
test::TestRequest as HttpTestRequest, test::TestRequest as HttpTestRequest,
Extensions, Request, body Extensions, Request,
}; };
use actix_router::{Path, ResourceDef, Url}; use actix_router::{Path, ResourceDef, Url};
use actix_service::{IntoService, IntoServiceFactory, Service, ServiceFactory}; use actix_service::{IntoService, IntoServiceFactory, Service, ServiceFactory};