mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-25 14:49:20 +02:00
drop unpin constraint
This commit is contained in:
@ -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>
|
||||
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,
|
||||
{
|
||||
service: CloneableService<S>,
|
||||
expect: CloneableService<X>,
|
||||
@ -181,14 +172,11 @@ where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
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,
|
||||
{
|
||||
/// Create http/1 dispatcher.
|
||||
pub(crate) fn new(
|
||||
@ -269,14 +257,11 @@ where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
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,
|
||||
{
|
||||
fn can_read(&self, cx: &mut Context) -> bool {
|
||||
if self
|
||||
@ -312,7 +297,9 @@ where
|
||||
let len = self.write_buf.len();
|
||||
let mut written = 0;
|
||||
while written < len {
|
||||
match Pin::new(&mut self.io).poll_write(cx, &self.write_buf[written..]) {
|
||||
match unsafe { Pin::new_unchecked(&mut self.io) }
|
||||
.poll_write(cx, &self.write_buf[written..])
|
||||
{
|
||||
Poll::Ready(Ok(0)) => {
|
||||
return Err(DispatchError::Io(io::Error::new(
|
||||
io::ErrorKind::WriteZero,
|
||||
@ -383,32 +370,36 @@ where
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
State::ExpectCall(ref mut fut) => match Pin::new(fut).poll(cx) {
|
||||
Poll::Ready(Ok(req)) => {
|
||||
self.send_continue();
|
||||
self.state = State::ServiceCall(self.service.call(req));
|
||||
continue;
|
||||
State::ExpectCall(ref mut fut) => {
|
||||
match unsafe { Pin::new_unchecked(fut) }.poll(cx) {
|
||||
Poll::Ready(Ok(req)) => {
|
||||
self.send_continue();
|
||||
self.state = State::ServiceCall(self.service.call(req));
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
let res: Response = e.into().into();
|
||||
let (res, body) = res.replace_body(());
|
||||
Some(self.send_response(res, body.into_body())?)
|
||||
}
|
||||
Poll::Pending => None,
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
let res: Response = e.into().into();
|
||||
let (res, body) = res.replace_body(());
|
||||
Some(self.send_response(res, body.into_body())?)
|
||||
}
|
||||
State::ServiceCall(ref mut fut) => {
|
||||
match unsafe { Pin::new_unchecked(fut) }.poll(cx) {
|
||||
Poll::Ready(Ok(res)) => {
|
||||
let (res, body) = res.into().replace_body(());
|
||||
self.state = self.send_response(res, body)?;
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
let res: Response = e.into().into();
|
||||
let (res, body) = res.replace_body(());
|
||||
Some(self.send_response(res, body.into_body())?)
|
||||
}
|
||||
Poll::Pending => None,
|
||||
}
|
||||
Poll::Pending => None,
|
||||
},
|
||||
State::ServiceCall(ref mut fut) => match Pin::new(fut).poll(cx) {
|
||||
Poll::Ready(Ok(res)) => {
|
||||
let (res, body) = res.into().replace_body(());
|
||||
self.state = self.send_response(res, body)?;
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
let res: Response = e.into().into();
|
||||
let (res, body) = res.replace_body(());
|
||||
Some(self.send_response(res, body.into_body())?)
|
||||
}
|
||||
Poll::Pending => None,
|
||||
},
|
||||
}
|
||||
State::SendPayload(ref mut stream) => {
|
||||
loop {
|
||||
if self.write_buf.len() < HW_BUFFER_SIZE {
|
||||
@ -472,7 +463,7 @@ where
|
||||
// Handle `EXPECT: 100-Continue` header
|
||||
let req = if req.head().expect() {
|
||||
let mut task = self.expect.call(req);
|
||||
match Pin::new(&mut task).poll(cx) {
|
||||
match unsafe { Pin::new_unchecked(&mut task) }.poll(cx) {
|
||||
Poll::Ready(Ok(req)) => {
|
||||
self.send_continue();
|
||||
req
|
||||
@ -491,7 +482,7 @@ where
|
||||
|
||||
// Call service
|
||||
let mut task = self.service.call(req);
|
||||
match Pin::new(&mut task).poll(cx) {
|
||||
match unsafe { Pin::new_unchecked(&mut task) }.poll(cx) {
|
||||
Poll::Ready(Ok(res)) => {
|
||||
let (res, body) = res.into().replace_body(());
|
||||
self.send_response(res, body)
|
||||
@ -689,26 +680,37 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S, B, X, U> Unpin for Dispatcher<T, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, S, B, X, U> Future for Dispatcher<T, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
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,
|
||||
{
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
||||
#[inline]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
match self.inner {
|
||||
match self.as_mut().inner {
|
||||
DispatcherState::Normal(ref mut inner) => {
|
||||
inner.poll_keepalive(cx)?;
|
||||
|
||||
@ -818,7 +820,7 @@ where
|
||||
}
|
||||
}
|
||||
DispatcherState::Upgrade(ref mut fut) => {
|
||||
Pin::new(fut).poll(cx).map_err(|e| {
|
||||
unsafe { Pin::new_unchecked(fut) }.poll(cx).map_err(|e| {
|
||||
error!("Upgrade handler error: {}", e);
|
||||
DispatchError::Upgrade
|
||||
})
|
||||
@ -894,7 +896,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_req_parse_err() {
|
||||
let mut sys = actix_rt::System::new("test");
|
||||
let _ = sys.block_on(lazy(|| {
|
||||
let _ = sys.block_on(lazy(|cx| {
|
||||
let buf = TestBuffer::new("GET /test HTTP/1\r\n\r\n");
|
||||
|
||||
let mut h1 = Dispatcher::<_, _, _, _, UpgradeHandler<TestBuffer>>::new(
|
||||
@ -907,7 +909,10 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
);
|
||||
assert!(h1.poll().is_err());
|
||||
match Pin::new(&mut h1).poll(cx) {
|
||||
Poll::Pending => panic!(),
|
||||
Poll::Ready(res) => assert!(res.is_err()),
|
||||
}
|
||||
|
||||
if let DispatcherState::Normal(ref inner) = h1.inner {
|
||||
assert!(inner.flags.contains(Flags::READ_DISCONNECT));
|
||||
|
@ -228,26 +228,23 @@ impl Inner {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use actix_rt::Runtime;
|
||||
use futures::future::{lazy, result};
|
||||
use futures::future::{poll_fn, ready};
|
||||
|
||||
#[test]
|
||||
fn test_unread_data() {
|
||||
Runtime::new()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let (_, mut payload) = Payload::create(false);
|
||||
Runtime::new().unwrap().block_on(async {
|
||||
let (_, mut payload) = Payload::create(false);
|
||||
|
||||
payload.unread_data(Bytes::from("data"));
|
||||
assert!(!payload.is_empty());
|
||||
assert_eq!(payload.len(), 4);
|
||||
payload.unread_data(Bytes::from("data"));
|
||||
assert!(!payload.is_empty());
|
||||
assert_eq!(payload.len(), 4);
|
||||
|
||||
assert_eq!(
|
||||
Poll::Ready(Some(Bytes::from("data"))),
|
||||
payload.next_item().await.ok().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Bytes::from("data"),
|
||||
poll_fn(|cx| payload.readany(cx)).await.unwrap().unwrap()
|
||||
);
|
||||
|
||||
result(())
|
||||
})
|
||||
.unwrap();
|
||||
ready(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -39,11 +39,7 @@ where
|
||||
S::Error: Into<Error>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
P: Unpin,
|
||||
{
|
||||
/// Create new `HttpService` instance with default config.
|
||||
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self {
|
||||
@ -81,20 +77,13 @@ where
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
P: Unpin,
|
||||
{
|
||||
pub fn expect<X1>(self, expect: X1) -> H1Service<T, P, S, B, X1, U>
|
||||
where
|
||||
X1: ServiceFactory<Request = Request, Response = Request>,
|
||||
X1::Error: Into<Error>,
|
||||
X1::InitError: fmt::Debug,
|
||||
X1::Future: Unpin,
|
||||
X1::Service: Unpin,
|
||||
<X1::Service as Service>::Future: Unpin,
|
||||
{
|
||||
H1Service {
|
||||
expect,
|
||||
@ -111,9 +100,6 @@ where
|
||||
U1: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U1::Error: fmt::Display,
|
||||
U1::InitError: fmt::Debug,
|
||||
U1::Future: Unpin,
|
||||
U1::Service: Unpin,
|
||||
<U1::Service as Service>::Future: Unpin,
|
||||
{
|
||||
H1Service {
|
||||
upgrade,
|
||||
@ -139,20 +125,13 @@ impl<T, P, S, B, X, U> ServiceFactory for H1Service<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Service: Unpin,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
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,
|
||||
U: ServiceFactory<
|
||||
Config = SrvConfig,
|
||||
Request = (Request, Framed<T, Codec>),
|
||||
@ -160,10 +139,6 @@ where
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
type Config = SrvConfig;
|
||||
type Request = Io<T, P>;
|
||||
@ -188,30 +163,24 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[pin_project::pin_project]
|
||||
pub struct H1ServiceResponse<T, P, S, B, X, U>
|
||||
where
|
||||
S: ServiceFactory<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
X: ServiceFactory<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::InitError: fmt::Debug,
|
||||
X::Future: Unpin,
|
||||
X::Service: Unpin,
|
||||
<X::Service as Service>::Future: Unpin,
|
||||
U: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
#[pin]
|
||||
fut: S::Future,
|
||||
#[pin]
|
||||
fut_ex: Option<X::Future>,
|
||||
#[pin]
|
||||
fut_upg: Option<U::Future>,
|
||||
expect: Option<X::Service>,
|
||||
upgrade: Option<U::Service>,
|
||||
@ -227,51 +196,45 @@ where
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: ServiceFactory<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::InitError: fmt::Debug,
|
||||
X::Future: Unpin,
|
||||
X::Service: Unpin,
|
||||
<X::Service as Service>::Future: Unpin,
|
||||
U: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
type Output =
|
||||
Result<H1ServiceHandler<T, P, S::Service, B, X::Service, U::Service>, ()>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
if let Some(ref mut fut) = this.fut_ex {
|
||||
let expect = ready!(Pin::new(fut)
|
||||
if let Some(fut) = this.fut_ex.as_pin_mut() {
|
||||
let expect = ready!(fut
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||
this.expect = Some(expect);
|
||||
this.fut_ex.take();
|
||||
this = self.as_mut().project();
|
||||
*this.expect = Some(expect);
|
||||
this.fut_ex.set(None);
|
||||
}
|
||||
|
||||
if let Some(ref mut fut) = this.fut_upg {
|
||||
let upgrade = ready!(Pin::new(fut)
|
||||
if let Some(fut) = this.fut_upg.as_pin_mut() {
|
||||
let upgrade = ready!(fut
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||
this.upgrade = Some(upgrade);
|
||||
this.fut_ex.take();
|
||||
this = self.as_mut().project();
|
||||
*this.upgrade = Some(upgrade);
|
||||
this.fut_ex.set(None);
|
||||
}
|
||||
|
||||
let result = ready!(Pin::new(&mut this.fut)
|
||||
let result = ready!(this
|
||||
.fut
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
||||
|
||||
Poll::Ready(result.map(|service| {
|
||||
let this = self.as_mut().project();
|
||||
H1ServiceHandler::new(
|
||||
this.cfg.take().unwrap(),
|
||||
service,
|
||||
@ -295,18 +258,14 @@ pub struct H1ServiceHandler<T, P, S, B, X, U> {
|
||||
|
||||
impl<T, P, S, B, X, U> H1ServiceHandler<T, P, S, B, X, U>
|
||||
where
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X::Future: Unpin,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()> + Unpin,
|
||||
U::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
P: Unpin,
|
||||
{
|
||||
fn new(
|
||||
cfg: ServiceConfig,
|
||||
@ -329,18 +288,14 @@ where
|
||||
impl<T, P, S, B, X, U> Service for H1ServiceHandler<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()> + Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
type Request = Io<T, P>;
|
||||
type Response = ();
|
||||
|
@ -11,6 +11,7 @@ use crate::h1::{Codec, Message};
|
||||
use crate::response::Response;
|
||||
|
||||
/// Send http/1 response
|
||||
#[pin_project::pin_project]
|
||||
pub struct SendResponse<T, B> {
|
||||
res: Option<Message<(Response<()>, BodySize)>>,
|
||||
body: Option<ResponseBody<B>>,
|
||||
@ -34,7 +35,7 @@ where
|
||||
|
||||
impl<T, B> Future for SendResponse<T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
T: AsyncRead + AsyncWrite,
|
||||
B: MessageBody,
|
||||
{
|
||||
type Output = Result<Framed<T, Codec>, Error>;
|
||||
|
@ -35,6 +35,7 @@ use crate::response::Response;
|
||||
const CHUNK_SIZE: usize = 16_384;
|
||||
|
||||
/// Dispatcher for HTTP/2 protocol
|
||||
#[pin_project::pin_project]
|
||||
pub struct Dispatcher<T: IoStream, S: Service<Request = Request>, B: MessageBody> {
|
||||
service: CloneableService<S>,
|
||||
connection: Connection<T, Bytes>,
|
||||
@ -46,24 +47,13 @@ pub struct Dispatcher<T: IoStream, S: Service<Request = Request>, B: MessageBody
|
||||
_t: PhantomData<B>,
|
||||
}
|
||||
|
||||
impl<T, S, B> Unpin for Dispatcher<T, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, S, B> Dispatcher<T, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
pub(crate) fn new(
|
||||
@ -107,9 +97,9 @@ impl<T, S, B> Future for Dispatcher<T, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
type Output = Result<(), DispatchError>;
|
||||
@ -122,7 +112,7 @@ where
|
||||
match Pin::new(&mut this.connection).poll_accept(cx) {
|
||||
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
||||
Poll::Ready(Some(Err(err))) => return Poll::Ready(Err(err.into())),
|
||||
Poll::Ready(Some(Ok((req, _)))) => {
|
||||
Poll::Ready(Some(Ok((req, res)))) => {
|
||||
// update keep-alive expire
|
||||
if this.ka_timer.is_some() {
|
||||
if let Some(expire) = this.config.keep_alive_expire() {
|
||||
@ -131,7 +121,6 @@ where
|
||||
}
|
||||
|
||||
let (parts, body) = req.into_parts();
|
||||
// let b: () = body;
|
||||
let mut req = Request::with_payload(Payload::<
|
||||
crate::payload::PayloadStream,
|
||||
>::H2(
|
||||
@ -150,20 +139,20 @@ where
|
||||
on_connect.set(&mut req.extensions_mut());
|
||||
}
|
||||
|
||||
// tokio_executor::current_thread::spawn(ServiceResponse::<
|
||||
// S::Future,
|
||||
// S::Response,
|
||||
// S::Error,
|
||||
// B,
|
||||
// > {
|
||||
// state: ServiceResponseState::ServiceCall(
|
||||
// this.service.call(req),
|
||||
// Some(res),
|
||||
// ),
|
||||
// config: this.config.clone(),
|
||||
// buffer: None,
|
||||
// _t: PhantomData,
|
||||
// });
|
||||
tokio_executor::current_thread::spawn(ServiceResponse::<
|
||||
S::Future,
|
||||
S::Response,
|
||||
S::Error,
|
||||
B,
|
||||
> {
|
||||
state: ServiceResponseState::ServiceCall(
|
||||
this.service.call(req),
|
||||
Some(res),
|
||||
),
|
||||
config: this.config.clone(),
|
||||
buffer: None,
|
||||
_t: PhantomData,
|
||||
});
|
||||
}
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
@ -171,6 +160,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
struct ServiceResponse<F, I, E, B> {
|
||||
state: ServiceResponseState<F, B>,
|
||||
config: ServiceConfig,
|
||||
@ -185,9 +175,9 @@ enum ServiceResponseState<F, B> {
|
||||
|
||||
impl<F, I, E, B> ServiceResponse<F, I, E, B>
|
||||
where
|
||||
F: Future<Output = Result<I, E>> + Unpin,
|
||||
E: Into<Error> + Unpin + 'static,
|
||||
I: Into<Response<B>> + Unpin + 'static,
|
||||
F: Future<Output = Result<I, E>>,
|
||||
E: Into<Error> + 'static,
|
||||
I: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
fn prepare_response(
|
||||
@ -253,25 +243,27 @@ where
|
||||
|
||||
impl<F, I, E, B> Future for ServiceResponse<F, I, E, B>
|
||||
where
|
||||
F: Future<Output = Result<I, E>> + Unpin,
|
||||
E: Into<Error> + Unpin + 'static,
|
||||
I: Into<Response<B>> + Unpin + 'static,
|
||||
F: Future<Output = Result<I, E>>,
|
||||
E: Into<Error> + 'static,
|
||||
I: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
match this.state {
|
||||
ServiceResponseState::ServiceCall(ref mut call, ref mut send) => {
|
||||
match Pin::new(call).poll(cx) {
|
||||
match unsafe { Pin::new_unchecked(call) }.poll(cx) {
|
||||
Poll::Ready(Ok(res)) => {
|
||||
let (res, body) = res.into().replace_body(());
|
||||
|
||||
let mut send = send.take().unwrap();
|
||||
let mut size = body.size();
|
||||
let h2_res = this.prepare_response(res.head(), &mut size);
|
||||
let h2_res =
|
||||
self.as_mut().prepare_response(res.head(), &mut size);
|
||||
this = self.as_mut().project();
|
||||
|
||||
let stream = match send.send_response(h2_res, size.is_eof()) {
|
||||
Err(e) => {
|
||||
@ -284,8 +276,9 @@ where
|
||||
if size.is_eof() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
this.state = ServiceResponseState::SendPayload(stream, body);
|
||||
Pin::new(this).poll(cx)
|
||||
*this.state =
|
||||
ServiceResponseState::SendPayload(stream, body);
|
||||
self.poll(cx)
|
||||
}
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
@ -295,7 +288,9 @@ where
|
||||
|
||||
let mut send = send.take().unwrap();
|
||||
let mut size = body.size();
|
||||
let h2_res = this.prepare_response(res.head(), &mut size);
|
||||
let h2_res =
|
||||
self.as_mut().prepare_response(res.head(), &mut size);
|
||||
this = self.as_mut().project();
|
||||
|
||||
let stream = match send.send_response(h2_res, size.is_eof()) {
|
||||
Err(e) => {
|
||||
@ -308,11 +303,11 @@ where
|
||||
if size.is_eof() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
this.state = ServiceResponseState::SendPayload(
|
||||
*this.state = ServiceResponseState::SendPayload(
|
||||
stream,
|
||||
body.into_body(),
|
||||
);
|
||||
Pin::new(this).poll(cx)
|
||||
self.poll(cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -356,7 +351,7 @@ where
|
||||
chunk.len(),
|
||||
CHUNK_SIZE,
|
||||
));
|
||||
this.buffer = Some(chunk);
|
||||
*this.buffer = Some(chunk);
|
||||
}
|
||||
Poll::Ready(Some(Err(e))) => {
|
||||
error!("Response payload stream error: {:?}", e);
|
||||
|
@ -37,12 +37,10 @@ pub struct H2Service<T, P, S, B> {
|
||||
impl<T, P, S, B> H2Service<T, P, S, B>
|
||||
where
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Future: Unpin,
|
||||
<S::Service as Service>::Future: Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody + 'static,
|
||||
P: Unpin,
|
||||
{
|
||||
/// Create new `HttpService` instance.
|
||||
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self {
|
||||
@ -83,12 +81,10 @@ impl<T, P, S, B> ServiceFactory for H2Service<T, P, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Future: Unpin,
|
||||
<S::Service as Service>::Future: Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody + 'static,
|
||||
P: Unpin,
|
||||
{
|
||||
type Config = SrvConfig;
|
||||
type Request = Io<T, P>;
|
||||
@ -109,7 +105,9 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[pin_project::pin_project]
|
||||
pub struct H2ServiceResponse<T, P, S: ServiceFactory, B> {
|
||||
#[pin]
|
||||
fut: S::Future,
|
||||
cfg: Option<ServiceConfig>,
|
||||
on_connect: Option<rc::Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
|
||||
@ -120,19 +118,18 @@ impl<T, P, S, B> Future for H2ServiceResponse<T, P, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Future: Unpin,
|
||||
<S::Service as Service>::Future: Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody + 'static,
|
||||
P: Unpin,
|
||||
{
|
||||
type Output = Result<H2ServiceHandler<T, P, S::Service, B>, S::InitError>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = self.as_mut().project();
|
||||
|
||||
Poll::Ready(ready!(Pin::new(&mut this.fut).poll(cx)).map(|service| {
|
||||
Poll::Ready(ready!(this.fut.poll(cx)).map(|service| {
|
||||
let this = self.as_mut().project();
|
||||
H2ServiceHandler::new(
|
||||
this.cfg.take().unwrap(),
|
||||
this.on_connect.clone(),
|
||||
@ -153,11 +150,10 @@ pub struct H2ServiceHandler<T, P, S, B> {
|
||||
impl<T, P, S, B> H2ServiceHandler<T, P, S, B>
|
||||
where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
P: Unpin,
|
||||
{
|
||||
fn new(
|
||||
cfg: ServiceConfig,
|
||||
@ -177,11 +173,10 @@ impl<T, P, S, B> Service for H2ServiceHandler<T, P, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
P: Unpin,
|
||||
{
|
||||
type Request = Io<T, P>;
|
||||
type Response = ();
|
||||
@ -235,9 +230,9 @@ pub struct H2ServiceHandlerResponse<T, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
state: State<T, S, B>,
|
||||
@ -247,9 +242,9 @@ impl<T, S, B> Future for H2ServiceHandlerResponse<T, S, B>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody,
|
||||
{
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
@ -80,6 +80,11 @@ impl<P> Request<P> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Get request's payload
|
||||
pub fn payload(&mut self) -> &mut Payload<P> {
|
||||
&mut self.payload
|
||||
}
|
||||
|
||||
/// Get request's payload
|
||||
pub fn take_payload(&mut self) -> Payload<P> {
|
||||
std::mem::replace(&mut self.payload, Payload::None)
|
||||
|
@ -635,8 +635,8 @@ impl ResponseBuilder {
|
||||
/// `ResponseBuilder` can not be used after this call.
|
||||
pub fn streaming<S, E>(&mut self, stream: S) -> Response
|
||||
where
|
||||
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
|
||||
E: Into<Error> + Unpin + 'static,
|
||||
S: Stream<Item = Result<Bytes, E>> + 'static,
|
||||
E: Into<Error> + 'static,
|
||||
{
|
||||
self.body(Body::from_message(BodyStream::new(stream)))
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use actix_service::{IntoServiceFactory, Service, ServiceFactory};
|
||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||
use futures::{ready, Future};
|
||||
use h2::server::{self, Handshake};
|
||||
use pin_project::{pin_project, project};
|
||||
|
||||
use crate::body::MessageBody;
|
||||
use crate::builder::HttpServiceBuilder;
|
||||
@ -35,12 +36,10 @@ pub struct HttpService<T, P, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler
|
||||
impl<T, S, B> HttpService<T, (), S, B>
|
||||
where
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
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,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
/// Create builder for `HttpService` instance.
|
||||
@ -52,14 +51,11 @@ where
|
||||
impl<T, P, S, B> HttpService<T, P, S, B>
|
||||
where
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
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,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody + 'static,
|
||||
P: Unpin,
|
||||
{
|
||||
/// Create new `HttpService` instance.
|
||||
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self {
|
||||
@ -94,14 +90,11 @@ where
|
||||
impl<T, P, S, B, X, U> HttpService<T, P, S, B, 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::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody,
|
||||
P: Unpin,
|
||||
{
|
||||
/// Provide service for `EXPECT: 100-Continue` support.
|
||||
///
|
||||
@ -113,9 +106,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,
|
||||
{
|
||||
HttpService {
|
||||
expect,
|
||||
@ -140,9 +131,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,
|
||||
{
|
||||
HttpService {
|
||||
upgrade,
|
||||
@ -166,22 +155,17 @@ where
|
||||
|
||||
impl<T, P, S, B, X, U> ServiceFactory for HttpService<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream + Unpin,
|
||||
T: IoStream,
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Service: Unpin,
|
||||
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,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody + '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, h1::Codec>),
|
||||
@ -189,10 +173,7 @@ where
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin + 'static,
|
||||
P: Unpin,
|
||||
<U::Service as Service>::Future: 'static,
|
||||
{
|
||||
type Config = SrvConfig;
|
||||
type Request = ServerIo<T, P>;
|
||||
@ -217,6 +198,7 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[pin_project]
|
||||
pub struct HttpServiceResponse<
|
||||
T,
|
||||
P,
|
||||
@ -225,8 +207,11 @@ pub struct HttpServiceResponse<
|
||||
X: ServiceFactory,
|
||||
U: ServiceFactory,
|
||||
> {
|
||||
#[pin]
|
||||
fut: S::Future,
|
||||
#[pin]
|
||||
fut_ex: Option<X::Future>,
|
||||
#[pin]
|
||||
fut_upg: Option<U::Future>,
|
||||
expect: Option<X::Service>,
|
||||
upgrade: Option<U::Service>,
|
||||
@ -239,53 +224,50 @@ impl<T, P, S, B, X, U> Future for HttpServiceResponse<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: ServiceFactory<Request = Request>,
|
||||
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,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
<S::Service as Service>::Future: 'static,
|
||||
B: MessageBody + 'static,
|
||||
X: ServiceFactory<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<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin + 'static,
|
||||
P: Unpin,
|
||||
<U::Service as Service>::Future: 'static,
|
||||
{
|
||||
type Output =
|
||||
Result<HttpServiceHandler<T, P, S::Service, B, X::Service, U::Service>, ()>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
if let Some(ref mut fut) = this.fut_ex {
|
||||
let expect = ready!(Pin::new(fut)
|
||||
if let Some(fut) = this.fut_ex.as_pin_mut() {
|
||||
let expect = ready!(fut
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||
this.expect = Some(expect);
|
||||
this.fut_ex.take();
|
||||
this = self.as_mut().project();
|
||||
*this.expect = Some(expect);
|
||||
this.fut_ex.set(None);
|
||||
}
|
||||
|
||||
if let Some(ref mut fut) = this.fut_upg {
|
||||
let upgrade = ready!(Pin::new(fut)
|
||||
if let Some(fut) = this.fut_upg.as_pin_mut() {
|
||||
let upgrade = ready!(fut
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||
this.upgrade = Some(upgrade);
|
||||
this.fut_ex.take();
|
||||
this = self.as_mut().project();
|
||||
*this.upgrade = Some(upgrade);
|
||||
this.fut_ex.set(None);
|
||||
}
|
||||
|
||||
let result = ready!(Pin::new(&mut this.fut)
|
||||
let result = ready!(this
|
||||
.fut
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
||||
Poll::Ready(result.map(|service| {
|
||||
let this = self.as_mut().project();
|
||||
HttpServiceHandler::new(
|
||||
this.cfg.take().unwrap(),
|
||||
service,
|
||||
@ -309,19 +291,15 @@ pub struct HttpServiceHandler<T, P, S, B, X, U> {
|
||||
|
||||
impl<T, P, S, B, X, U> HttpServiceHandler<T, P, S, B, X, U>
|
||||
where
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
S::Future: Unpin,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X::Future: Unpin,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||
U::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
P: Unpin,
|
||||
{
|
||||
fn new(
|
||||
cfg: ServiceConfig,
|
||||
@ -343,19 +321,16 @@ where
|
||||
|
||||
impl<T, P, S, B, X, U> Service for HttpServiceHandler<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream + Unpin,
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
type Request = ServerIo<T, P>;
|
||||
type Response = ();
|
||||
@ -442,22 +417,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_project]
|
||||
enum State<T, S, B, X, U>
|
||||
where
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S::Future: Unpin + 'static,
|
||||
S: Service<Request = Request>,
|
||||
S::Future: 'static,
|
||||
S::Error: Into<Error>,
|
||||
T: IoStream + Unpin,
|
||||
T: IoStream,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
H1(h1::Dispatcher<T, S, B, X, U>),
|
||||
H2(Dispatcher<Io<T>, S, B>),
|
||||
H1(#[pin] h1::Dispatcher<T, S, B, X, U>),
|
||||
H2(#[pin] Dispatcher<Io<T>, S, B>),
|
||||
Unknown(
|
||||
Option<(
|
||||
T,
|
||||
@ -480,21 +454,21 @@ where
|
||||
),
|
||||
}
|
||||
|
||||
#[pin_project]
|
||||
pub struct HttpServiceHandlerResponse<T, S, B, X, U>
|
||||
where
|
||||
T: IoStream + Unpin,
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
#[pin]
|
||||
state: State<T, S, B, X, U>,
|
||||
}
|
||||
|
||||
@ -502,25 +476,45 @@ const HTTP2_PREFACE: [u8; 14] = *b"PRI * HTTP/2.0";
|
||||
|
||||
impl<T, S, B, X, U> Future for HttpServiceHandlerResponse<T, S, B, X, U>
|
||||
where
|
||||
T: IoStream + Unpin,
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S::Error: Into<Error> + Unpin + 'static,
|
||||
S::Future: Unpin + 'static,
|
||||
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Future: 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X::Future: Unpin,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||
U::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
{
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
match self.state {
|
||||
State::H1(ref mut disp) => Pin::new(disp).poll(cx),
|
||||
State::H2(ref mut disp) => Pin::new(disp).poll(cx),
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
self.project().state.poll(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S, B, X, U> State<T, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error> + 'static,
|
||||
S::Response: Into<Response<B>> + 'static,
|
||||
B: MessageBody + 'static,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
{
|
||||
#[project]
|
||||
fn poll(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Result<(), DispatchError>> {
|
||||
#[project]
|
||||
match self.as_mut().project() {
|
||||
State::H1(disp) => disp.poll(cx),
|
||||
State::H2(disp) => disp.poll(cx),
|
||||
State::Unknown(ref mut data) => {
|
||||
if let Some(ref mut item) = data {
|
||||
loop {
|
||||
@ -549,15 +543,15 @@ where
|
||||
inner: io,
|
||||
unread: Some(buf),
|
||||
};
|
||||
self.state = State::Handshake(Some((
|
||||
self.set(State::Handshake(Some((
|
||||
server::handshake(io),
|
||||
cfg,
|
||||
srv,
|
||||
peer_addr,
|
||||
on_connect,
|
||||
)));
|
||||
))));
|
||||
} else {
|
||||
self.state = State::H1(h1::Dispatcher::with_timeout(
|
||||
self.set(State::H1(h1::Dispatcher::with_timeout(
|
||||
io,
|
||||
h1::Codec::new(cfg.clone()),
|
||||
cfg,
|
||||
@ -567,7 +561,7 @@ where
|
||||
expect,
|
||||
upgrade,
|
||||
on_connect,
|
||||
))
|
||||
)))
|
||||
}
|
||||
self.poll(cx)
|
||||
}
|
||||
@ -585,9 +579,9 @@ where
|
||||
panic!()
|
||||
};
|
||||
let (_, cfg, srv, peer_addr, on_connect) = data.take().unwrap();
|
||||
self.state = State::H2(Dispatcher::new(
|
||||
self.set(State::H2(Dispatcher::new(
|
||||
srv, conn, on_connect, cfg, None, peer_addr,
|
||||
));
|
||||
)));
|
||||
self.poll(cx)
|
||||
}
|
||||
}
|
||||
@ -595,13 +589,13 @@ where
|
||||
}
|
||||
|
||||
/// Wrapper for `AsyncRead + AsyncWrite` types
|
||||
#[pin_project::pin_project]
|
||||
struct Io<T> {
|
||||
unread: Option<BytesMut>,
|
||||
#[pin]
|
||||
inner: T,
|
||||
}
|
||||
|
||||
impl<T> Unpin for Io<T> {}
|
||||
|
||||
impl<T: io::Read> io::Read for Io<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
if let Some(mut bytes) = self.unread.take() {
|
||||
@ -627,7 +621,7 @@ impl<T: io::Write> io::Write for Io<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsyncRead + Unpin> AsyncRead for Io<T> {
|
||||
impl<T: AsyncRead> AsyncRead for Io<T> {
|
||||
// unsafe fn initializer(&self) -> io::Initializer {
|
||||
// self.get_mut().inner.initializer()
|
||||
// }
|
||||
@ -641,7 +635,19 @@ impl<T: AsyncRead + Unpin> AsyncRead for Io<T> {
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Pin::new(&mut self.get_mut().inner).poll_read(cx, buf)
|
||||
let this = self.project();
|
||||
|
||||
if let Some(mut bytes) = this.unread.take() {
|
||||
let size = std::cmp::min(buf.len(), bytes.len());
|
||||
buf[..size].copy_from_slice(&bytes[..size]);
|
||||
if bytes.len() > size {
|
||||
bytes.split_to(size);
|
||||
*this.unread = Some(bytes);
|
||||
}
|
||||
Poll::Ready(Ok(size))
|
||||
} else {
|
||||
this.inner.poll_read(cx, buf)
|
||||
}
|
||||
}
|
||||
|
||||
// fn poll_read_vectored(
|
||||
@ -653,32 +659,24 @@ impl<T: AsyncRead + Unpin> AsyncRead for Io<T> {
|
||||
// }
|
||||
}
|
||||
|
||||
impl<T: AsyncWrite + Unpin> tokio_io::AsyncWrite for Io<T> {
|
||||
impl<T: AsyncWrite> tokio_io::AsyncWrite for Io<T> {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Pin::new(&mut self.get_mut().inner).poll_write(cx, buf)
|
||||
self.project().inner.poll_write(cx, buf)
|
||||
}
|
||||
|
||||
// fn poll_write_vectored(
|
||||
// self: Pin<&mut Self>,
|
||||
// cx: &mut Context<'_>,
|
||||
// bufs: &[io::IoSlice<'_>],
|
||||
// ) -> Poll<io::Result<usize>> {
|
||||
// self.get_mut().inner.poll_write_vectored(cx, bufs)
|
||||
// }
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.get_mut().inner).poll_flush(cx)
|
||||
self.project().inner.poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_shutdown(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<io::Result<()>> {
|
||||
Pin::new(&mut self.get_mut().inner).poll_shutdown(cx)
|
||||
self.project().inner.poll_shutdown(cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,17 +11,17 @@ use super::{Codec, Frame, Message};
|
||||
pub struct Transport<S, T>
|
||||
where
|
||||
S: Service<Request = Frame, Response = Message> + 'static,
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
T: AsyncRead + AsyncWrite,
|
||||
{
|
||||
inner: FramedTransport<S, T, Codec>,
|
||||
}
|
||||
|
||||
impl<S, T> Transport<S, T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
S: Service<Request = Frame, Response = Message> + Unpin,
|
||||
T: AsyncRead + AsyncWrite,
|
||||
S: Service<Request = Frame, Response = Message>,
|
||||
S::Future: 'static,
|
||||
S::Error: Unpin + 'static,
|
||||
S::Error: 'static,
|
||||
{
|
||||
pub fn new<F: IntoService<S>>(io: T, service: F) -> Self {
|
||||
Transport {
|
||||
@ -38,10 +38,10 @@ where
|
||||
|
||||
impl<S, T> Future for Transport<S, T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
S: Service<Request = Frame, Response = Message> + Unpin,
|
||||
T: AsyncRead + AsyncWrite,
|
||||
S: Service<Request = Frame, Response = Message>,
|
||||
S::Future: 'static,
|
||||
S::Error: Unpin + 'static,
|
||||
S::Error: 'static,
|
||||
{
|
||||
type Output = Result<(), FramedTransportError<S::Error, Codec>>;
|
||||
|
||||
|
Reference in New Issue
Block a user