drop unpin constraint

master
Nikolay Kim 3 years ago
parent 687884fb94
commit 1ffa7d18d3
  1. 3
      actix-http/Cargo.toml
  2. 34
      actix-http/examples/echo.rs
  3. 29
      actix-http/examples/echo2.rs
  4. 73
      actix-http/src/body.rs
  5. 55
      actix-http/src/builder.rs
  6. 60
      actix-http/src/client/connection.rs
  7. 129
      actix-http/src/client/connector.rs
  8. 8
      actix-http/src/client/error.rs
  9. 35
      actix-http/src/client/pool.rs
  10. 2
      actix-http/src/config.rs
  11. 20
      actix-http/src/error.rs
  12. 103
      actix-http/src/h1/dispatcher.rs
  13. 33
      actix-http/src/h1/payload.rs
  14. 95
      actix-http/src/h1/service.rs
  15. 3
      actix-http/src/h1/utils.rs
  16. 93
      actix-http/src/h2/dispatcher.rs
  17. 59
      actix-http/src/h2/service.rs
  18. 5
      actix-http/src/request.rs
  19. 4
      actix-http/src/response.rs
  20. 262
      actix-http/src/service.rs
  21. 14
      actix-http/src/ws/transport.rs
  22. 88
      actix-http/tests/test_client.rs
  23. 545
      actix-http/tests/test_openssl.rs
  24. 474
      actix-http/tests/test_rustls.rs
  25. 462
      actix-http/tests/test_rustls_server.rs
  26. 925
      actix-http/tests/test_server.rs
  27. 480
      actix-http/tests/test_ssl_server.rs
  28. 100
      actix-http/tests/test_ws.rs
  29. 37
      test-server/src/lib.rs
  30. 47
      tests/cert.pem
  31. 76
      tests/key.pem

@ -74,6 +74,7 @@ language-tags = "0.2"
log = "0.4"
mime = "0.3"
percent-encoding = "2.1"
pin-project = "0.4.5"
rand = "0.7"
regex = "1.0"
serde = "1.0"
@ -107,7 +108,7 @@ webpki-roots = { version = "0.18", optional = true }
[dev-dependencies]
actix-rt = "1.0.0-alpha.1"
actix-server = { version = "0.8.0-alpha.1", features=["openssl"] }
actix-server = { version = "0.8.0-alpha.1", features=["openssl", "rustls"] }
actix-connect = { version = "1.0.0-alpha.1", features=["openssl"] }
actix-http-test = { version = "0.3.0-alpha.1", features=["openssl"] }
env_logger = "0.6"

@ -1,9 +1,9 @@
use std::{env, io};
use actix_http::{error::PayloadError, HttpService, Request, Response};
use actix_http::{Error, HttpService, Request, Response};
use actix_server::Server;
use bytes::BytesMut;
use futures::{Future, Stream};
use futures::StreamExt;
use http::header::HeaderValue;
use log::info;
@ -17,20 +17,22 @@ fn main() -> io::Result<()> {
.client_timeout(1000)
.client_disconnect(1000)
.finish(|mut req: Request| {
req.take_payload()
.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, PayloadError>(body)
})
.and_then(|bytes| {
info!("request body: {:?}", bytes);
let mut res = Response::Ok();
res.header(
"x-head",
HeaderValue::from_static("dummy value!"),
);
Ok(res.body(bytes))
})
async move {
let mut body = BytesMut::new();
while let Some(item) = req.payload().next().await {
body.extend_from_slice(&item?);
}
info!("request body: {:?}", body);
Ok::<_, Error>(
Response::Ok()
.header(
"x-head",
HeaderValue::from_static("dummy value!"),
)
.body(body),
)
}
})
})?
.run()

@ -1,25 +1,22 @@
use std::{env, io};
use actix_http::http::HeaderValue;
use actix_http::{error::PayloadError, Error, HttpService, Request, Response};
use actix_http::{Error, HttpService, Request, Response};
use actix_server::Server;
use bytes::BytesMut;
use futures::{Future, Stream};
use futures::StreamExt;
use log::info;
fn handle_request(mut req: Request) -> impl Future<Item = Response, Error = Error> {
req.take_payload()
.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, PayloadError>(body)
})
.from_err()
.and_then(|bytes| {
info!("request body: {:?}", bytes);
let mut res = Response::Ok();
res.header("x-head", HeaderValue::from_static("dummy value!"));
Ok(res.body(bytes))
})
async fn handle_request(mut req: Request) -> Result<Response, Error> {
let mut body = BytesMut::new();
while let Some(item) = req.payload().next().await {
body.extend_from_slice(&item?)
}
info!("request body: {:?}", body);
Ok(Response::Ok()
.header("x-head", HeaderValue::from_static("dummy value!"))
.body(body))
}
fn main() -> io::Result<()> {
@ -28,7 +25,7 @@ fn main() -> io::Result<()> {
Server::build()
.bind("echo", "127.0.0.1:8080", || {
HttpService::build().finish(|_req: Request| handle_request(_req))
HttpService::build().finish(handle_request)
})?
.run()
}

@ -5,6 +5,7 @@ use std::{fmt, mem};
use bytes::{Bytes, BytesMut};
use futures::Stream;
use pin_project::{pin_project, project};
use crate::error::Error;
@ -31,7 +32,7 @@ impl BodySize {
}
/// Type that provides this trait can be streamed to a peer.
pub trait MessageBody: Unpin {
pub trait MessageBody {
fn size(&self) -> BodySize;
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>>;
@ -57,6 +58,7 @@ impl<T: MessageBody> MessageBody for Box<T> {
}
}
#[pin_project]
pub enum ResponseBody<B> {
Body(B),
Other(Body),
@ -106,8 +108,13 @@ impl<B: MessageBody> MessageBody for ResponseBody<B> {
impl<B: MessageBody> Stream for ResponseBody<B> {
type Item = Result<Bytes, Error>;
#[project]
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
self.get_mut().poll_next(cx)
#[project]
match self.project() {
ResponseBody::Body(ref mut body) => body.poll_next(cx),
ResponseBody::Other(ref mut body) => body.poll_next(cx),
}
}
}
@ -243,7 +250,7 @@ impl From<serde_json::Value> for Body {
impl<S> From<SizedStream<S>> for Body
where
S: Stream<Item = Result<Bytes, Error>> + Unpin + 'static,
S: Stream<Item = Result<Bytes, Error>> + 'static,
{
fn from(s: SizedStream<S>) -> Body {
Body::from_message(s)
@ -252,7 +259,7 @@ where
impl<S, E> From<BodyStream<S, E>> for Body
where
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
S: Stream<Item = Result<Bytes, E>> + 'static,
E: Into<Error> + 'static,
{
fn from(s: BodyStream<S, E>) -> Body {
@ -350,7 +357,9 @@ impl MessageBody for String {
/// Type represent streaming body.
/// Response does not contain `content-length` header and appropriate transfer encoding is used.
#[pin_project]
pub struct BodyStream<S, E> {
#[pin]
stream: S,
_t: PhantomData<E>,
}
@ -368,16 +377,9 @@ where
}
}
impl<S, E> Unpin for BodyStream<S, E>
where
S: Stream<Item = Result<Bytes, E>> + Unpin,
E: Into<Error>,
{
}
impl<S, E> MessageBody for BodyStream<S, E>
where
S: Stream<Item = Result<Bytes, E>> + Unpin,
S: Stream<Item = Result<Bytes, E>>,
E: Into<Error>,
{
fn size(&self) -> BodySize {
@ -385,7 +387,9 @@ where
}
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
Pin::new(&mut self.stream)
unsafe { Pin::new_unchecked(self) }
.project()
.stream
.poll_next(cx)
.map(|res| res.map(|res| res.map_err(std::convert::Into::into)))
}
@ -393,8 +397,10 @@ where
/// Type represent streaming body. This body implementation should be used
/// if total size of stream is known. Data get sent as is without using transfer encoding.
#[pin_project]
pub struct SizedStream<S> {
size: u64,
#[pin]
stream: S,
}
@ -409,20 +415,25 @@ where
impl<S> MessageBody for SizedStream<S>
where
S: Stream<Item = Result<Bytes, Error>> + Unpin,
S: Stream<Item = Result<Bytes, Error>>,
{
fn size(&self) -> BodySize {
BodySize::Sized64(self.size)
}
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
Pin::new(&mut self.stream).poll_next(cx)
unsafe { Pin::new_unchecked(self) }
.project()
.stream
.poll_next(cx)
}
}
#[cfg(test)]
mod tests {
use super::*;
use actix_http_test::block_on;
use futures::future::{lazy, poll_fn};
impl Body {
pub(crate) fn get_ref(&self) -> &[u8] {
@ -450,8 +461,8 @@ mod tests {
assert_eq!("test".size(), BodySize::Sized(4));
assert_eq!(
"test".poll_next().unwrap(),
Async::Ready(Some(Bytes::from("test")))
block_on(poll_fn(|cx| "test".poll_next(cx))).unwrap().ok(),
Some(Bytes::from("test"))
);
}
@ -467,8 +478,10 @@ mod tests {
assert_eq!((&b"test"[..]).size(), BodySize::Sized(4));
assert_eq!(
(&b"test"[..]).poll_next().unwrap(),
Async::Ready(Some(Bytes::from("test")))
block_on(poll_fn(|cx| (&b"test"[..]).poll_next(cx)))
.unwrap()
.ok(),
Some(Bytes::from("test"))
);
}
@ -479,8 +492,10 @@ mod tests {
assert_eq!(Vec::from("test").size(), BodySize::Sized(4));
assert_eq!(
Vec::from("test").poll_next().unwrap(),
Async::Ready(Some(Bytes::from("test")))
block_on(poll_fn(|cx| Vec::from("test").poll_next(cx)))
.unwrap()
.ok(),
Some(Bytes::from("test"))
);
}
@ -492,8 +507,8 @@ mod tests {
assert_eq!(b.size(), BodySize::Sized(4));
assert_eq!(
b.poll_next().unwrap(),
Async::Ready(Some(Bytes::from("test")))
block_on(poll_fn(|cx| b.poll_next(cx))).unwrap().ok(),
Some(Bytes::from("test"))
);
}
@ -505,8 +520,8 @@ mod tests {
assert_eq!(b.size(), BodySize::Sized(4));
assert_eq!(
b.poll_next().unwrap(),
Async::Ready(Some(Bytes::from("test")))
block_on(poll_fn(|cx| b.poll_next(cx))).unwrap().ok(),
Some(Bytes::from("test"))
);
}
@ -520,22 +535,22 @@ mod tests {
assert_eq!(b.size(), BodySize::Sized(4));
assert_eq!(
b.poll_next().unwrap(),
Async::Ready(Some(Bytes::from("test")))
block_on(poll_fn(|cx| b.poll_next(cx))).unwrap().ok(),
Some(Bytes::from("test"))
);
}
#[test]
fn test_unit() {
assert_eq!(().size(), BodySize::Empty);
assert_eq!(().poll_next().unwrap(), Async::Ready(None));
assert!(block_on(poll_fn(|cx| ().poll_next(cx))).is_none());
}
#[test]
fn test_box() {
let mut val = Box::new(());
assert_eq!(val.size(), BodySize::Empty);
assert_eq!(val.poll_next().unwrap(), Async::Ready(None));
assert!(block_on(poll_fn(|cx| val.poll_next(cx))).is_none());
}
#[test]

@ -33,11 +33,9 @@ pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler<T>> {
impl<T, S> HttpServiceBuilder<T, S, ExpectHandler, UpgradeHandler<T>>
where
S: ServiceFactory<Config = SrvConfig, Request = Request>,
S::Error: Into<Error> + Unpin + 'static,
S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug,
S::Future: Unpin,
S::Service: Unpin,
<S::Service as Service>::Future: Unpin + 'static,
<S::Service as Service>::Future: 'static,
{
/// Create instance of `ServiceConfigBuilder`
pub fn new() -> Self {
@ -56,17 +54,13 @@ where
impl<T, S, X, U> HttpServiceBuilder<T, S, X, U>
where
S: ServiceFactory<Config = SrvConfig, Request = Request>,
S::Error: Into<Error> + Unpin + 'static,
S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug,
S::Future: Unpin,
S::Service: Unpin,
<S::Service as Service>::Future: Unpin + 'static,
<S::Service as Service>::Future: 'static,
X: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
X::Error: Into<Error>,
X::InitError: fmt::Debug,
X::Future: Unpin,
X::Service: Unpin,
<X::Service as Service>::Future: Unpin + 'static,
<X::Service as Service>::Future: 'static,
U: ServiceFactory<
Config = SrvConfig,
Request = (Request, Framed<T, Codec>),
@ -74,9 +68,7 @@ where
>,
U::Error: fmt::Display,
U::InitError: fmt::Debug,
U::Future: Unpin,
U::Service: Unpin,
<U::Service as Service>::Future: Unpin + 'static,
<U::Service as Service>::Future: 'static,
{
/// Set server keep-alive setting.
///
@ -124,9 +116,7 @@ where
X1: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
X1::Error: Into<Error>,
X1::InitError: fmt::Debug,
X1::Future: Unpin,
X1::Service: Unpin,
<X1::Service as Service>::Future: Unpin + 'static,
<X1::Service as Service>::Future: 'static,
{
HttpServiceBuilder {
keep_alive: self.keep_alive,
@ -153,9 +143,7 @@ where
>,
U1::Error: fmt::Display,
U1::InitError: fmt::Debug,
U1::Future: Unpin,
U1::Service: Unpin,
<U1::Service as Service>::Future: Unpin + 'static,
<U1::Service as Service>::Future: 'static,
{
HttpServiceBuilder {
keep_alive: self.keep_alive,
@ -186,13 +174,10 @@ where
where
B: MessageBody + 'static,
F: IntoServiceFactory<S>,
S::Future: Unpin,
S::Error: Into<Error> + Unpin + 'static,
S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + Unpin + 'static,
S::Service: Unpin,
<S::Service as Service>::Future: Unpin + 'static,
P: Unpin,
S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static,
{
let cfg = ServiceConfig::new(
self.keep_alive,
@ -210,13 +195,10 @@ where
where
B: MessageBody + 'static,
F: IntoServiceFactory<S>,
S::Error: Into<Error> + Unpin + 'static,
S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + Unpin + 'static,
S::Future: Unpin,
S::Service: Unpin,
<S::Service as Service>::Future: Unpin + 'static,
P: Unpin,
S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static,
{
let cfg = ServiceConfig::new(
self.keep_alive,
@ -231,13 +213,10 @@ where
where
B: MessageBody + 'static,
F: IntoServiceFactory<S>,
S::Error: Into<Error> + Unpin + 'static,
S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + Unpin + 'static,
S::Future: Unpin,
S::Service: Unpin,
<S::Service as Service>::Future: Unpin + 'static,
P: Unpin,
S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static,
{
let cfg = ServiceConfig::new(
self.keep_alive,

@ -6,6 +6,7 @@ use actix_codec::{AsyncRead, AsyncWrite, Framed};
use bytes::{Buf, Bytes};
use futures::future::{err, Either, Future, FutureExt, LocalBoxFuture, Ready};
use h2::client::SendRequest;
use pin_project::{pin_project, project};
use crate::body::MessageBody;
use crate::h1::ClientCodec;
@ -42,9 +43,7 @@ pub trait Connection {
fn open_tunnel<H: Into<RequestHeadType>>(self, head: H) -> Self::TunnelFuture;
}
pub(crate) trait ConnectionLifetime:
AsyncRead + AsyncWrite + Unpin + 'static
{
pub(crate) trait ConnectionLifetime: AsyncRead + AsyncWrite + 'static {
/// Close connection
fn close(&mut self);
@ -73,7 +72,7 @@ where
}
}
impl<T: AsyncRead + AsyncWrite> IoConnection<T> {
impl<T: AsyncRead + AsyncWrite + Unpin> IoConnection<T> {
pub(crate) fn new(
io: ConnectionType<T>,
created: time::Instant,
@ -205,24 +204,27 @@ where
}
}
#[pin_project]
pub enum EitherIo<A, B> {
A(A),
B(B),
A(#[pin] A),
B(#[pin] B),
}
impl<A, B> AsyncRead for EitherIo<A, B>
where
A: AsyncRead + Unpin,
B: AsyncRead + Unpin,
A: AsyncRead,
B: AsyncRead,
{
#[project]
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<io::Result<usize>> {
match self.get_mut() {
EitherIo::A(ref mut val) => Pin::new(val).poll_read(cx, buf),
EitherIo::B(ref mut val) => Pin::new(val).poll_read(cx, buf),
#[project]
match self.project() {
EitherIo::A(val) => val.poll_read(cx, buf),
EitherIo::B(val) => val.poll_read(cx, buf),
}
}
@ -236,37 +238,44 @@ where
impl<A, B> AsyncWrite for EitherIo<A, B>
where
A: AsyncWrite + Unpin,
B: AsyncWrite + Unpin,
A: AsyncWrite,
B: AsyncWrite,
{
#[project]
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context,
buf: &[u8],
) -> Poll<io::Result<usize>> {
match self.get_mut() {
EitherIo::A(ref mut val) => Pin::new(val).poll_write(cx, buf),
EitherIo::B(ref mut val) => Pin::new(val).poll_write(cx, buf),
#[project]
match self.project() {
EitherIo::A(val) => val.poll_write(cx, buf),
EitherIo::B(val) => val.poll_write(cx, buf),
}
}
#[project]
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
match self.get_mut() {
EitherIo::A(ref mut val) => Pin::new(val).poll_flush(cx),
EitherIo::B(ref mut val) => Pin::new(val).poll_flush(cx),
#[project]
match self.project() {
EitherIo::A(val) => val.poll_flush(cx),
EitherIo::B(val) => val.poll_flush(cx),
}
}
#[project]
fn poll_shutdown(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<io::Result<()>> {
match self.get_mut() {
EitherIo::A(ref mut val) => Pin::new(val).poll_shutdown(cx),
EitherIo::B(ref mut val) => Pin::new(val).poll_shutdown(cx),
#[project]
match self.project() {
EitherIo::A(val) => val.poll_shutdown(cx),
EitherIo::B(val) => val.poll_shutdown(cx),
}
}
#[project]
fn poll_write_buf<U: Buf>(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
@ -275,9 +284,10 @@ where
where
Self: Sized,
{
match self.get_mut() {
EitherIo::A(ref mut val) => Pin::new(val).poll_write_buf(cx, buf),
EitherIo::B(ref mut val) => Pin::new(val).poll_write_buf(cx, buf),
#[project]
match self.project() {
EitherIo::A(val) => val.poll_write_buf(cx, buf),
EitherIo::B(val) => val.poll_write_buf(cx, buf),
}
}
}

@ -62,8 +62,8 @@ pub struct Connector<T, U> {
_t: PhantomData<U>,
}
trait Io: AsyncRead + AsyncWrite {}
impl<T: AsyncRead + AsyncWrite> Io for T {}
trait Io: AsyncRead + AsyncWrite + Unpin {}
impl<T: AsyncRead + AsyncWrite + Unpin> Io for T {}
impl Connector<(), ()> {
#[allow(clippy::new_ret_no_self)]
@ -123,7 +123,6 @@ impl<T, U> Connector<T, U> {
Response = TcpConnection<Uri, U1>,
Error = actix_connect::ConnectError,
> + Clone,
T1::Future: Unpin,
{
Connector {
connector,
@ -222,7 +221,7 @@ where
{
let connector = TimeoutService::new(
self.timeout,
apply_fn(UnpinWrapper(self.connector), |msg: Connect, srv| {
apply_fn(self.connector, |msg: Connect, srv| {
srv.call(TcpConnect::new(msg.uri).set_addr(msg.addr))
})
.map_err(ConnectError::from)
@ -257,35 +256,33 @@ where
let ssl_service = TimeoutService::new(
self.timeout,
pipeline(
apply_fn(
UnpinWrapper(self.connector.clone()),
|msg: Connect, srv| {
srv.call(TcpConnect::new(msg.uri).set_addr(msg.addr))
},
)
apply_fn(self.connector.clone(), |msg: Connect, srv| {
srv.call(TcpConnect::new(msg.uri).set_addr(msg.addr))
})
.map_err(ConnectError::from),
)
.and_then(match self.ssl {
#[cfg(feature = "openssl")]
SslConnector::Openssl(ssl) => OpensslConnector::service(ssl)
.map(|stream| {
let sock = stream.into_parts().0;
let h2 = sock
.ssl()
.selected_alpn_protocol()
.map(|protos| protos.windows(2).any(|w| w == H2))
.unwrap_or(false);
if h2 {
(Box::new(sock) as Box<dyn Io + Unpin>, Protocol::Http2)
} else {
(Box::new(sock) as Box<dyn Io + Unpin>, Protocol::Http1)
}
})
.map_err(ConnectError::from),
SslConnector::Openssl(ssl) => service(
OpensslConnector::service(ssl)
.map(|stream| {
let sock = stream.into_parts().0;
let h2 = sock
.ssl()
.selected_alpn_protocol()
.map(|protos| protos.windows(2).any(|w| w == H2))
.unwrap_or(false);
if h2 {
(Box::new(sock) as Box<dyn Io>, Protocol::Http2)
} else {
(Box::new(sock) as Box<dyn Io>, Protocol::Http1)
}
})
.map_err(ConnectError::from),
),
#[cfg(feature = "rustls")]
SslConnector::Rustls(ssl) => service(
UnpinWrapper(RustlsConnector::service(ssl))
RustlsConnector::service(ssl)
.map_err(ConnectError::from)
.map(|stream| {
let sock = stream.into_parts().0;
@ -296,15 +293,9 @@ where
.map(|protos| protos.windows(2).any(|w| w == H2))
.unwrap_or(false);
if h2 {
(
Box::new(sock) as Box<dyn Io + Unpin>,
Protocol::Http2,
)
(Box::new(sock) as Box<dyn Io>, Protocol::Http2)
} else {
(
Box::new(sock) as Box<dyn Io + Unpin>,
Protocol::Http1,
)
(Box::new(sock) as Box<dyn Io>, Protocol::Http1)
}
}),
),
@ -317,7 +308,7 @@ where
let tcp_service = TimeoutService::new(
self.timeout,
apply_fn(UnpinWrapper(self.connector), |msg: Connect, srv| {
apply_fn(self.connector, |msg: Connect, srv| {
srv.call(TcpConnect::new(msg.uri).set_addr(msg.addr))
})
.map_err(ConnectError::from)
@ -348,42 +339,6 @@ where
}
}
#[derive(Clone)]
struct UnpinWrapper<T: Clone>(T);
impl<T: Clone> Unpin for UnpinWrapper<T> {}
impl<T: Service + Clone> Service for UnpinWrapper<T> {
type Request = T::Request;
type Response = T::Response;
type Error = T::Error;
type Future = UnpinWrapperFut<T>;
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), T::Error>> {
self.0.poll_ready(cx)
}
fn call(&mut self, req: T::Request) -> Self::Future {
UnpinWrapperFut {
fut: self.0.call(req),
}
}
}
struct UnpinWrapperFut<T: Service> {
fut: T::Future,
}
impl<T: Service> Unpin for UnpinWrapperFut<T> {}
impl<T: Service> Future for UnpinWrapperFut<T> {
type Output = Result<T::Response, T::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
unsafe { Pin::new_unchecked(&mut self.get_mut().fut) }.poll(cx)
}
}
#[cfg(not(any(feature = "openssl", feature = "rustls")))]
mod connect_impl {
use std::task::{Context, Poll};
@ -396,9 +351,8 @@ mod connect_impl {
pub(crate) struct InnerConnector<T, Io>
where
Io: AsyncRead + AsyncWrite + 'static,
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
{
pub(crate) tcp_pool: ConnectionPool<T, Io>,
@ -406,9 +360,8 @@ mod connect_impl {
impl<T, Io> Clone for InnerConnector<T, Io>
where
Io: AsyncRead + AsyncWrite + 'static,
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
{
fn clone(&self) -> Self {
@ -422,9 +375,7 @@ mod connect_impl {
where
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T::Future: Unpin,
{
type Request = Connect;
type Response = IoConnection<Io>;
@ -465,8 +416,6 @@ mod connect_impl {
Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T1: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError>,
T2: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>,
T1::Future: Unpin,
T2::Future: Unpin,
{
pub(crate) tcp_pool: ConnectionPool<T1, Io1>,
pub(crate) ssl_pool: ConnectionPool<T2, Io2>,
@ -477,13 +426,9 @@ mod connect_impl {
Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T1: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T2: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T1::Future: Unpin,
T2::Future: Unpin,
{
fn clone(&self) -> Self {
InnerConnector {
@ -498,13 +443,9 @@ mod connect_impl {
Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T1: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T2: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T1::Future: Unpin,
T2::Future: Unpin,
{
type Request = Connect;
type Response = EitherConnection<Io1, Io2>;
@ -532,14 +473,14 @@ mod connect_impl {
}
}
#[pin_project::pin_project]
pub(crate) struct InnerConnectorResponseA<T, Io1, Io2>
where
Io1: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T::Future: Unpin,
{
#[pin]
fut: <ConnectionPool<T, Io1> as Service>::Future,
_t: PhantomData<Io2>,
}
@ -547,9 +488,7 @@ mod connect_impl {
impl<T, Io1, Io2> Future for InnerConnectorResponseA<T, Io1, Io2>
where
T: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T::Future: Unpin,
Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static,
{
@ -563,14 +502,14 @@ mod connect_impl {
}
}
#[pin_project::pin_project]
pub(crate) struct InnerConnectorResponseB<T, Io1, Io2>
where
Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T::Future: Unpin,
{
#[pin]
fut: <ConnectionPool<T, Io2> as Service>::Future,
_t: PhantomData<Io1>,
}
@ -578,9 +517,7 @@ mod connect_impl {
impl<T, Io1, Io2> Future for InnerConnectorResponseB<T, Io1, Io2>
where
T: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T::Future: Unpin,
Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static,
{

@ -3,8 +3,8 @@ use std::io;
use derive_more::{Display, From};
use trust_dns_resolver::error::ResolveError;
#[cfg(feature = "ssl")]
use openssl::ssl::{Error as SslError, HandshakeError};
#[cfg(feature = "openssl")]
use open_ssl::ssl::{Error as SslError, HandshakeError};
use crate::error::{Error, ParseError, ResponseError};
use crate::http::Error as HttpError;
@ -18,7 +18,7 @@ pub enum ConnectError {
SslIsNotSupported,
/// SSL error
#[cfg(feature = "ssl")]
#[cfg(feature = "openssl")]
#[display(fmt = "{}", _0)]
SslError(SslError),
@ -63,7 +63,7 @@ impl From<actix_connect::ConnectError> for ConnectError {
}
}
#[cfg(feature = "ssl")]
#[cfg(feature = "openssl")]
impl<T> From<HandshakeError<T>> for ConnectError {
fn from(err: HandshakeError<T>) -> ConnectError {
match err {

@ -46,11 +46,9 @@ pub(crate) struct ConnectionPool<T, Io: 'static>(Rc<RefCell<T>>, Rc<RefCell<Inne
impl<T, Io> ConnectionPool<T, Io>
where
Io: AsyncRead + AsyncWrite + 'static,
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T::Future: Unpin,
{
pub(crate) fn new(
connector: T,
@ -89,9 +87,7 @@ impl<T, Io> Service for ConnectionPool<T, Io>
where
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
+ Unpin
+ 'static,
T::Future: Unpin,
{
type Request = Connect;
type Response = IoConnection<Io>;
@ -400,7 +396,7 @@ struct CloseConnection<T> {
impl<T> CloseConnection<T>
where
T: AsyncWrite,
T: AsyncWrite + Unpin,
{
fn new(io: T, timeout: Duration) -> Self {
CloseConnection {
@ -416,10 +412,12 @@ where
{
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
match Pin::new(&mut self.timeout).poll(cx) {
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
let this = self.get_mut();
match Pin::new(&mut this.timeout).poll(cx) {
Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => match Pin::new(&mut self.io).poll_shutdown(cx) {
Poll::Pending => match Pin::new(&mut this.io).poll_shutdown(cx) {
Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => Poll::Pending,
},
@ -429,7 +427,7 @@ where
struct ConnectorPoolSupport<T, Io>
where
Io: AsyncRead + AsyncWrite + 'static,
Io: AsyncRead + AsyncWrite + Unpin + 'static,
{
connector: T,
inner: Rc<RefCell<Inner<Io>>>,
@ -438,14 +436,13 @@ where
impl<T, Io> Future for ConnectorPoolSupport<T, Io>
where
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>
+ Unpin,
T::Future: Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>,
T::Future: 'static,
{
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = self.get_mut();
let this = unsafe { self.get_unchecked_mut() };
let mut inner = this.inner.as_ref().borrow_mut();
inner.waker.register(cx.waker());
@ -512,7 +509,7 @@ where
impl<F, Io> OpenWaitingConnection<F, Io>
where
F: Future<Output = Result<(Io, Protocol), ConnectError>> + Unpin + 'static,
F: Future<Output = Result<(Io, Protocol), ConnectError>> + 'static,
Io: AsyncRead + AsyncWrite + Unpin + 'static,
{
fn spawn(
@ -546,13 +543,13 @@ where
impl<F, Io> Future for OpenWaitingConnection<F, Io>
where
F: Future<Output = Result<(Io, Protocol), ConnectError>> + Unpin,
F: Future<Output = Result<(Io, Protocol), ConnectError>>,
Io: AsyncRead + AsyncWrite + Unpin,
{
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let this = self.get_mut();
let this = unsafe { self.get_unchecked_mut() };
if let Some(ref mut h2) = this.h2 {
return match Pin::new(h2).poll(cx) {
@ -577,7 +574,7 @@ where
};
}
match Pin::new(&mut this.fut).poll(cx) {
match unsafe { Pin::new_unchecked(&mut this.fut) }.poll(cx) {
Poll::Ready(Err(err)) => {
let _ = this.inner.take();
if let Some(rx) = this.rx.take() {
@ -596,7 +593,7 @@ where
Poll::Ready(())
} else {
this.h2 = Some(handshake(io).boxed_local());
Pin::new(this).poll(cx)
unsafe { Pin::new_unchecked(this) }.poll(cx)
}
}
Poll::Pending => Poll::Pending,

@ -277,7 +277,7 @@ mod tests {
fn test_date() {
let mut rt = System::new("test");
let _ = rt.block_on(future::lazy(|| {
let _ = rt.block_on(future::lazy(|_| {
let settings = ServiceConfig::new(KeepAlive::Os, 0, 0);
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
settings.set_date(&mut buf1);

@ -181,13 +181,13 @@ impl ResponseError for FormError {}
/// `InternalServerError` for `TimerError`
impl ResponseError for TimerError {}
#[cfg(feature = "ssl")]
#[cfg(feature = "openssl")]
/// `InternalServerError` for `openssl::ssl::Error`
impl ResponseError for openssl::ssl::Error {}
impl ResponseError for open_ssl::ssl::Error {}
#[cfg(feature = "ssl")]
#[cfg(feature = "openssl")]
/// `InternalServerError` for `openssl::ssl::HandshakeError`
impl ResponseError for openssl::ssl::HandshakeError<tokio_tcp::TcpStream> {}
impl<T: std::fmt::Debug> ResponseError for open_ssl::ssl::HandshakeError<T> {}
/// Return `BAD_REQUEST` for `de::value::Error`
impl ResponseError for DeError {
@ -383,12 +383,12 @@ impl ResponseError for PayloadError {
}
}
// /// Return `BadRequest` for `cookie::ParseError`
// impl ResponseError for crate::cookie::ParseError {
// fn error_response(&self) -> Response {
// Response::new(StatusCode::BAD_REQUEST)
// }
// }
/// Return `BadRequest` for `cookie::ParseError`
impl ResponseError for crate::cookie::ParseError {
fn error_response(&self) -> Response {
Response::new(StatusCode::BAD_REQUEST)
}
}
#[derive(Debug, Display, From)]
/// A set of errors that can occur during dispatching http requests

@ -48,14 +48,11 @@ pub struct Dispatcher<T, S, B, X, U>
where
S: Service<Request = Request>,
S::Error: Into<Error>,
S::Future: Unpin,
B: MessageBody,
X: Service<Request = Request, Response = Request>,
X::Error: Into<Error>,
X::Future: Unpin,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display,
U::Future: Unpin,
{
inner: DispatcherState<T, S, B, X, U>,
}
@ -64,14 +61,11 @@ enum DispatcherState<T, S, B, X, U>
where
S: Service<Request = Request>,
S::Error: Into<Error>,
S::Future: Unpin,
B: MessageBody,
X: Service<Request = Request, Response = Request>,
X::Error: Into<Error>,
X::Future: Unpin,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display,
U::Future: Unpin,
{
Normal(InnerDispatcher<T, S, B, X, U>),
Upgrade(U::Future),
@ -82,14 +76,11 @@ struct InnerDispatcher<T, S, B, X, U>