mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-30 18:34:36 +01:00
make actix-http compile with std::future
This commit is contained in:
parent
5cb2d500d1
commit
8cba1170e6
54
Cargo.toml
54
Cargo.toml
@ -28,19 +28,20 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
".",
|
# ".",
|
||||||
"awc",
|
# "awc",
|
||||||
"actix-http",
|
# #"actix-http",
|
||||||
"actix-cors",
|
# "actix-cors",
|
||||||
"actix-files",
|
# "actix-files",
|
||||||
"actix-framed",
|
# "actix-framed",
|
||||||
"actix-session",
|
# "actix-session",
|
||||||
"actix-identity",
|
# "actix-identity",
|
||||||
"actix-multipart",
|
# "actix-multipart",
|
||||||
"actix-web-actors",
|
# "actix-web-actors",
|
||||||
"actix-web-codegen",
|
# "actix-web-codegen",
|
||||||
"test-server",
|
# "test-server",
|
||||||
]
|
]
|
||||||
|
exclude = ["actix-http"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["brotli", "flate2-zlib", "client", "fail"]
|
default = ["brotli", "flate2-zlib", "client", "fail"]
|
||||||
@ -122,12 +123,23 @@ opt-level = 3
|
|||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
actix-web = { path = "." }
|
# actix-web = { path = "." }
|
||||||
actix-http = { path = "actix-http" }
|
# actix-http = { path = "actix-http" }
|
||||||
actix-http-test = { path = "test-server" }
|
# actix-http-test = { path = "test-server" }
|
||||||
actix-web-codegen = { path = "actix-web-codegen" }
|
# actix-web-codegen = { path = "actix-web-codegen" }
|
||||||
actix-web-actors = { path = "actix-web-actors" }
|
# actix-web-actors = { path = "actix-web-actors" }
|
||||||
actix-session = { path = "actix-session" }
|
# actix-session = { path = "actix-session" }
|
||||||
actix-files = { path = "actix-files" }
|
# actix-files = { path = "actix-files" }
|
||||||
actix-multipart = { path = "actix-multipart" }
|
# actix-multipart = { path = "actix-multipart" }
|
||||||
awc = { path = "awc" }
|
# awc = { path = "awc" }
|
||||||
|
|
||||||
|
actix-codec = { path = "../actix-net/actix-codec" }
|
||||||
|
actix-connect = { path = "../actix-net/actix-connect" }
|
||||||
|
actix-ioframe = { path = "../actix-net/actix-ioframe" }
|
||||||
|
actix-rt = { path = "../actix-net/actix-rt" }
|
||||||
|
actix-server = { path = "../actix-net/actix-server" }
|
||||||
|
actix-server-config = { path = "../actix-net/actix-server-config" }
|
||||||
|
actix-service = { path = "../actix-net/actix-service" }
|
||||||
|
actix-testing = { path = "../actix-net/actix-testing" }
|
||||||
|
actix-threadpool = { path = "../actix-net/actix-threadpool" }
|
||||||
|
actix-utils = { path = "../actix-net/actix-utils" }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "0.2.11"
|
version = "0.3.0-alpha.1"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix http primitives"
|
description = "Actix http primitives"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -13,10 +13,11 @@ categories = ["network-programming", "asynchronous",
|
|||||||
"web-programming::websocket"]
|
"web-programming::websocket"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
workspace = ".."
|
|
||||||
|
# workspace = ".."
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["ssl", "fail", "brotli", "flate2-zlib", "secure-cookies"]
|
features = ["openssl", "fail", "brotli", "flate2-zlib", "secure-cookies"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "actix_http"
|
name = "actix_http"
|
||||||
@ -26,10 +27,10 @@ path = "src/lib.rs"
|
|||||||
default = []
|
default = []
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
ssl = ["openssl", "actix-connect/ssl"]
|
openssl = ["open-ssl", "actix-connect/openssl"]
|
||||||
|
|
||||||
# rustls support
|
# rustls support
|
||||||
rust-tls = ["rustls", "webpki-roots", "actix-connect/rust-tls"]
|
rustls = ["rust-tls", "webpki-roots", "actix-connect/rustls"]
|
||||||
|
|
||||||
# brotli encoding, requires c compiler
|
# brotli encoding, requires c compiler
|
||||||
brotli = ["brotli2"]
|
brotli = ["brotli2"]
|
||||||
@ -47,23 +48,24 @@ fail = ["failure"]
|
|||||||
secure-cookies = ["ring"]
|
secure-cookies = ["ring"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-service = "0.4.1"
|
actix-service = "1.0.0-alpha.1"
|
||||||
actix-codec = "0.1.2"
|
actix-codec = "0.2.0-alpha.1"
|
||||||
actix-connect = "0.2.4"
|
actix-connect = "1.0.0-alpha.1"
|
||||||
actix-utils = "0.4.4"
|
actix-utils = "0.5.0-alpha.1"
|
||||||
actix-server-config = "0.1.2"
|
actix-server-config = "0.3.0-alpha.1"
|
||||||
actix-threadpool = "0.1.1"
|
actix-threadpool = "0.2.0-alpha.1"
|
||||||
|
|
||||||
base64 = "0.10"
|
base64 = "0.10"
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
copyless = "0.1.4"
|
copyless = "0.1.4"
|
||||||
|
chrono = "0.4.6"
|
||||||
derive_more = "0.15.0"
|
derive_more = "0.15.0"
|
||||||
either = "1.5.2"
|
either = "1.5.2"
|
||||||
encoding_rs = "0.8"
|
encoding_rs = "0.8"
|
||||||
futures = "0.1.25"
|
futures = "0.3.1"
|
||||||
hashbrown = "0.6.3"
|
hashbrown = "0.6.3"
|
||||||
h2 = "0.1.16"
|
h2 = "0.2.0-alpha.3"
|
||||||
http = "0.1.17"
|
http = "0.1.17"
|
||||||
httparse = "1.3"
|
httparse = "1.3"
|
||||||
indexmap = "1.2"
|
indexmap = "1.2"
|
||||||
@ -80,13 +82,16 @@ sha1 = "0.6"
|
|||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
serde_urlencoded = "0.6.1"
|
serde_urlencoded = "0.6.1"
|
||||||
time = "0.1.42"
|
time = "0.1.42"
|
||||||
tokio-tcp = "0.1.3"
|
|
||||||
tokio-timer = "0.2.8"
|
tokio = "=0.2.0-alpha.6"
|
||||||
tokio-current-thread = "0.1"
|
tokio-io = "=0.2.0-alpha.6"
|
||||||
trust-dns-resolver = { version="0.11.1", default-features = false }
|
tokio-net = "=0.2.0-alpha.6"
|
||||||
|
tokio-timer = "0.3.0-alpha.6"
|
||||||
|
tokio-executor = "=0.2.0-alpha.6"
|
||||||
|
trust-dns-resolver = { version="0.18.0-alpha.1", default-features = false }
|
||||||
|
|
||||||
# for secure cookie
|
# for secure cookie
|
||||||
ring = { version = "0.14.6", optional = true }
|
ring = { version = "0.16.9", optional = true }
|
||||||
|
|
||||||
# compression
|
# compression
|
||||||
brotli2 = { version="0.3.2", optional = true }
|
brotli2 = { version="0.3.2", optional = true }
|
||||||
@ -94,17 +99,25 @@ flate2 = { version="1.0.7", optional = true, default-features = false }
|
|||||||
|
|
||||||
# optional deps
|
# optional deps
|
||||||
failure = { version = "0.1.5", optional = true }
|
failure = { version = "0.1.5", optional = true }
|
||||||
openssl = { version="0.10", optional = true }
|
open-ssl = { version="0.10", package="openssl", optional = true }
|
||||||
rustls = { version = "0.15.2", optional = true }
|
rust-tls = { version = "0.16.0", package="rustls", optional = true }
|
||||||
webpki-roots = { version = "0.16", optional = true }
|
webpki-roots = { version = "0.18", optional = true }
|
||||||
chrono = "0.4.6"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "0.2.2"
|
actix-rt = "1.0.0-alpha.1"
|
||||||
actix-server = { version = "0.6.0", features=["ssl", "rust-tls"] }
|
actix-server = { version = "0.8.0-alpha.1", features=["openssl"] }
|
||||||
actix-connect = { version = "0.2.0", features=["ssl"] }
|
actix-connect = { version = "1.0.0-alpha.1", features=["openssl"] }
|
||||||
actix-http-test = { version = "0.2.4", features=["ssl"] }
|
#actix-http-test = { version = "0.2.4", features=["ssl"] }
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
openssl = { version="0.10" }
|
open-ssl = { version="0.10", package="openssl" }
|
||||||
tokio-tcp = "0.1"
|
|
||||||
|
[patch.crates-io]
|
||||||
|
actix-codec = { path = "../../actix-net/actix-codec" }
|
||||||
|
actix-connect = { path = "../../actix-net/actix-connect" }
|
||||||
|
actix-rt = { path = "../../actix-net/actix-rt" }
|
||||||
|
actix-server = { path = "../../actix-net/actix-server" }
|
||||||
|
actix-server-config = { path = "../../actix-net/actix-server-config" }
|
||||||
|
actix-service = { path = "../../actix-net/actix-service" }
|
||||||
|
actix-threadpool = { path = "../../actix-net/actix-threadpool" }
|
||||||
|
actix-utils = { path = "../../actix-net/actix-utils" }
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::{fmt, mem};
|
use std::{fmt, mem};
|
||||||
|
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures::{Async, Poll, Stream};
|
use futures::Stream;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
@ -29,10 +31,10 @@ impl BodySize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Type that provides this trait can be streamed to a peer.
|
/// Type that provides this trait can be streamed to a peer.
|
||||||
pub trait MessageBody {
|
pub trait MessageBody: Unpin {
|
||||||
fn size(&self) -> BodySize;
|
fn size(&self) -> BodySize;
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error>;
|
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageBody for () {
|
impl MessageBody for () {
|
||||||
@ -40,8 +42,8 @@ impl MessageBody for () {
|
|||||||
BodySize::Empty
|
BodySize::Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +52,8 @@ impl<T: MessageBody> MessageBody for Box<T> {
|
|||||||
self.as_ref().size()
|
self.as_ref().size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
self.as_mut().poll_next()
|
self.as_mut().poll_next(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,20 +95,19 @@ impl<B: MessageBody> MessageBody for ResponseBody<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
match self {
|
match self {
|
||||||
ResponseBody::Body(ref mut body) => body.poll_next(),
|
ResponseBody::Body(ref mut body) => body.poll_next(cx),
|
||||||
ResponseBody::Other(ref mut body) => body.poll_next(),
|
ResponseBody::Other(ref mut body) => body.poll_next(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: MessageBody> Stream for ResponseBody<B> {
|
impl<B: MessageBody> Stream for ResponseBody<B> {
|
||||||
type Item = Bytes;
|
type Item = Result<Bytes, Error>;
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||||
self.poll_next()
|
self.get_mut().poll_next(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,19 +145,19 @@ impl MessageBody for Body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
match self {
|
match self {
|
||||||
Body::None => Ok(Async::Ready(None)),
|
Body::None => Poll::Ready(None),
|
||||||
Body::Empty => Ok(Async::Ready(None)),
|
Body::Empty => Poll::Ready(None),
|
||||||
Body::Bytes(ref mut bin) => {
|
Body::Bytes(ref mut bin) => {
|
||||||
let len = bin.len();
|
let len = bin.len();
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(mem::replace(bin, Bytes::new()))))
|
Poll::Ready(Some(Ok(mem::replace(bin, Bytes::new()))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Body::Message(ref mut body) => body.poll_next(),
|
Body::Message(ref mut body) => body.poll_next(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +243,7 @@ impl From<serde_json::Value> for Body {
|
|||||||
|
|
||||||
impl<S> From<SizedStream<S>> for Body
|
impl<S> From<SizedStream<S>> for Body
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = Error> + 'static,
|
S: Stream<Item = Result<Bytes, Error>> + Unpin + 'static,
|
||||||
{
|
{
|
||||||
fn from(s: SizedStream<S>) -> Body {
|
fn from(s: SizedStream<S>) -> Body {
|
||||||
Body::from_message(s)
|
Body::from_message(s)
|
||||||
@ -251,8 +252,8 @@ where
|
|||||||
|
|
||||||
impl<S, E> From<BodyStream<S, E>> for Body
|
impl<S, E> From<BodyStream<S, E>> for Body
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = E> + 'static,
|
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
|
||||||
E: Into<Error> + 'static,
|
E: Into<Error> + Unpin + 'static,
|
||||||
{
|
{
|
||||||
fn from(s: BodyStream<S, E>) -> Body {
|
fn from(s: BodyStream<S, E>) -> Body {
|
||||||
Body::from_message(s)
|
Body::from_message(s)
|
||||||
@ -264,11 +265,11 @@ impl MessageBody for Bytes {
|
|||||||
BodySize::Sized(self.len())
|
BodySize::Sized(self.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(mem::replace(self, Bytes::new()))))
|
Poll::Ready(Some(Ok(mem::replace(self, Bytes::new()))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,13 +279,11 @@ impl MessageBody for BytesMut {
|
|||||||
BodySize::Sized(self.len())
|
BodySize::Sized(self.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(
|
Poll::Ready(Some(Ok(mem::replace(self, BytesMut::new()).freeze())))
|
||||||
mem::replace(self, BytesMut::new()).freeze(),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,11 +293,11 @@ impl MessageBody for &'static str {
|
|||||||
BodySize::Sized(self.len())
|
BodySize::Sized(self.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(Bytes::from_static(
|
Poll::Ready(Some(Ok(Bytes::from_static(
|
||||||
mem::replace(self, "").as_ref(),
|
mem::replace(self, "").as_ref(),
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
@ -310,13 +309,11 @@ impl MessageBody for &'static [u8] {
|
|||||||
BodySize::Sized(self.len())
|
BodySize::Sized(self.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(Bytes::from_static(mem::replace(
|
Poll::Ready(Some(Ok(Bytes::from_static(mem::replace(self, b"")))))
|
||||||
self, b"",
|
|
||||||
)))))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,14 +323,11 @@ impl MessageBody for Vec<u8> {
|
|||||||
BodySize::Sized(self.len())
|
BodySize::Sized(self.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(Bytes::from(mem::replace(
|
Poll::Ready(Some(Ok(Bytes::from(mem::replace(self, Vec::new())))))
|
||||||
self,
|
|
||||||
Vec::new(),
|
|
||||||
)))))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,11 +337,11 @@ impl MessageBody for String {
|
|||||||
BodySize::Sized(self.len())
|
BodySize::Sized(self.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(Bytes::from(
|
Poll::Ready(Some(Ok(Bytes::from(
|
||||||
mem::replace(self, String::new()).into_bytes(),
|
mem::replace(self, String::new()).into_bytes(),
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
@ -363,7 +357,7 @@ pub struct BodyStream<S, E> {
|
|||||||
|
|
||||||
impl<S, E> BodyStream<S, E>
|
impl<S, E> BodyStream<S, E>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = E>,
|
S: Stream<Item = Result<Bytes, E>>,
|
||||||
E: Into<Error>,
|
E: Into<Error>,
|
||||||
{
|
{
|
||||||
pub fn new(stream: S) -> Self {
|
pub fn new(stream: S) -> Self {
|
||||||
@ -376,15 +370,17 @@ where
|
|||||||
|
|
||||||
impl<S, E> MessageBody for BodyStream<S, E>
|
impl<S, E> MessageBody for BodyStream<S, E>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = E>,
|
S: Stream<Item = Result<Bytes, E>> + Unpin,
|
||||||
E: Into<Error>,
|
E: Into<Error> + Unpin,
|
||||||
{
|
{
|
||||||
fn size(&self) -> BodySize {
|
fn size(&self) -> BodySize {
|
||||||
BodySize::Stream
|
BodySize::Stream
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
self.stream.poll().map_err(std::convert::Into::into)
|
Pin::new(&mut self.stream)
|
||||||
|
.poll_next(cx)
|
||||||
|
.map(|res| res.map(|res| res.map_err(std::convert::Into::into)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +393,7 @@ pub struct SizedStream<S> {
|
|||||||
|
|
||||||
impl<S> SizedStream<S>
|
impl<S> SizedStream<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = Error>,
|
S: Stream<Item = Result<Bytes, Error>>,
|
||||||
{
|
{
|
||||||
pub fn new(size: u64, stream: S) -> Self {
|
pub fn new(size: u64, stream: S) -> Self {
|
||||||
SizedStream { size, stream }
|
SizedStream { size, stream }
|
||||||
@ -406,14 +402,14 @@ where
|
|||||||
|
|
||||||
impl<S> MessageBody for SizedStream<S>
|
impl<S> MessageBody for SizedStream<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = Error>,
|
S: Stream<Item = Result<Bytes, Error>> + Unpin,
|
||||||
{
|
{
|
||||||
fn size(&self) -> BodySize {
|
fn size(&self) -> BodySize {
|
||||||
BodySize::Sized64(self.size)
|
BodySize::Sized64(self.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
self.stream.poll()
|
Pin::new(&mut self.stream).poll_next(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use actix_codec::Framed;
|
use actix_codec::Framed;
|
||||||
use actix_server_config::ServerConfig as SrvConfig;
|
use actix_server_config::ServerConfig as SrvConfig;
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
use actix_service::{IntoServiceFactory, Service, ServiceFactory};
|
||||||
|
|
||||||
use crate::body::MessageBody;
|
use crate::body::MessageBody;
|
||||||
use crate::config::{KeepAlive, ServiceConfig};
|
use crate::config::{KeepAlive, ServiceConfig};
|
||||||
@ -32,9 +32,12 @@ pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler<T>> {
|
|||||||
|
|
||||||
impl<T, S> HttpServiceBuilder<T, S, ExpectHandler, UpgradeHandler<T>>
|
impl<T, S> HttpServiceBuilder<T, S, ExpectHandler, UpgradeHandler<T>>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
{
|
{
|
||||||
/// Create instance of `ServiceConfigBuilder`
|
/// Create instance of `ServiceConfigBuilder`
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -52,19 +55,28 @@ where
|
|||||||
|
|
||||||
impl<T, S, X, U> HttpServiceBuilder<T, S, X, U>
|
impl<T, S, X, U> HttpServiceBuilder<T, S, X, U>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
X: NewService<Config = SrvConfig, Request = Request, Response = Request>,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
|
X: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
X::InitError: fmt::Debug,
|
X::InitError: fmt::Debug,
|
||||||
U: NewService<
|
X::Future: Unpin,
|
||||||
|
X::Service: Unpin,
|
||||||
|
<X::Service as Service>::Future: Unpin + 'static,
|
||||||
|
U: ServiceFactory<
|
||||||
Config = SrvConfig,
|
Config = SrvConfig,
|
||||||
Request = (Request, Framed<T, Codec>),
|
Request = (Request, Framed<T, Codec>),
|
||||||
Response = (),
|
Response = (),
|
||||||
>,
|
>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
U::InitError: fmt::Debug,
|
U::InitError: fmt::Debug,
|
||||||
|
U::Future: Unpin,
|
||||||
|
U::Service: Unpin,
|
||||||
|
<U::Service as Service>::Future: Unpin + 'static,
|
||||||
{
|
{
|
||||||
/// Set server keep-alive setting.
|
/// Set server keep-alive setting.
|
||||||
///
|
///
|
||||||
@ -108,16 +120,19 @@ where
|
|||||||
/// request will be forwarded to main service.
|
/// request will be forwarded to main service.
|
||||||
pub fn expect<F, X1>(self, expect: F) -> HttpServiceBuilder<T, S, X1, U>
|
pub fn expect<F, X1>(self, expect: F) -> HttpServiceBuilder<T, S, X1, U>
|
||||||
where
|
where
|
||||||
F: IntoNewService<X1>,
|
F: IntoServiceFactory<X1>,
|
||||||
X1: NewService<Config = SrvConfig, Request = Request, Response = Request>,
|
X1: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
|
||||||
X1::Error: Into<Error>,
|
X1::Error: Into<Error>,
|
||||||
X1::InitError: fmt::Debug,
|
X1::InitError: fmt::Debug,
|
||||||
|
X1::Future: Unpin,
|
||||||
|
X1::Service: Unpin,
|
||||||
|
<X1::Service as Service>::Future: Unpin + 'static,
|
||||||
{
|
{
|
||||||
HttpServiceBuilder {
|
HttpServiceBuilder {
|
||||||
keep_alive: self.keep_alive,
|
keep_alive: self.keep_alive,
|
||||||
client_timeout: self.client_timeout,
|
client_timeout: self.client_timeout,
|
||||||
client_disconnect: self.client_disconnect,
|
client_disconnect: self.client_disconnect,
|
||||||
expect: expect.into_new_service(),
|
expect: expect.into_factory(),
|
||||||
upgrade: self.upgrade,
|
upgrade: self.upgrade,
|
||||||
on_connect: self.on_connect,
|
on_connect: self.on_connect,
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
@ -130,21 +145,24 @@ where
|
|||||||
/// and this service get called with original request and framed object.
|
/// and this service get called with original request and framed object.
|
||||||
pub fn upgrade<F, U1>(self, upgrade: F) -> HttpServiceBuilder<T, S, X, U1>
|
pub fn upgrade<F, U1>(self, upgrade: F) -> HttpServiceBuilder<T, S, X, U1>
|
||||||
where
|
where
|
||||||
F: IntoNewService<U1>,
|
F: IntoServiceFactory<U1>,
|
||||||
U1: NewService<
|
U1: ServiceFactory<
|
||||||
Config = SrvConfig,
|
Config = SrvConfig,
|
||||||
Request = (Request, Framed<T, Codec>),
|
Request = (Request, Framed<T, Codec>),
|
||||||
Response = (),
|
Response = (),
|
||||||
>,
|
>,
|
||||||
U1::Error: fmt::Display,
|
U1::Error: fmt::Display,
|
||||||
U1::InitError: fmt::Debug,
|
U1::InitError: fmt::Debug,
|
||||||
|
U1::Future: Unpin,
|
||||||
|
U1::Service: Unpin,
|
||||||
|
<U1::Service as Service>::Future: Unpin + 'static,
|
||||||
{
|
{
|
||||||
HttpServiceBuilder {
|
HttpServiceBuilder {
|
||||||
keep_alive: self.keep_alive,
|
keep_alive: self.keep_alive,
|
||||||
client_timeout: self.client_timeout,
|
client_timeout: self.client_timeout,
|
||||||
client_disconnect: self.client_disconnect,
|
client_disconnect: self.client_disconnect,
|
||||||
expect: self.expect,
|
expect: self.expect,
|
||||||
upgrade: Some(upgrade.into_new_service()),
|
upgrade: Some(upgrade.into_factory()),
|
||||||
on_connect: self.on_connect,
|
on_connect: self.on_connect,
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
@ -167,17 +185,21 @@ where
|
|||||||
pub fn h1<F, P, B>(self, service: F) -> H1Service<T, P, S, B, X, U>
|
pub fn h1<F, P, B>(self, service: F) -> H1Service<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
F: IntoNewService<S>,
|
F: IntoServiceFactory<S>,
|
||||||
S::Error: Into<Error>,
|
S::Future: Unpin,
|
||||||
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
let cfg = ServiceConfig::new(
|
let cfg = ServiceConfig::new(
|
||||||
self.keep_alive,
|
self.keep_alive,
|
||||||
self.client_timeout,
|
self.client_timeout,
|
||||||
self.client_disconnect,
|
self.client_disconnect,
|
||||||
);
|
);
|
||||||
H1Service::with_config(cfg, service.into_new_service())
|
H1Service::with_config(cfg, service.into_factory())
|
||||||
.expect(self.expect)
|
.expect(self.expect)
|
||||||
.upgrade(self.upgrade)
|
.upgrade(self.upgrade)
|
||||||
.on_connect(self.on_connect)
|
.on_connect(self.on_connect)
|
||||||
@ -187,37 +209,42 @@ where
|
|||||||
pub fn h2<F, P, B>(self, service: F) -> H2Service<T, P, S, B>
|
pub fn h2<F, P, B>(self, service: F) -> H2Service<T, P, S, B>
|
||||||
where
|
where
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
F: IntoNewService<S>,
|
F: IntoServiceFactory<S>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
let cfg = ServiceConfig::new(
|
let cfg = ServiceConfig::new(
|
||||||
self.keep_alive,
|
self.keep_alive,
|
||||||
self.client_timeout,
|
self.client_timeout,
|
||||||
self.client_disconnect,
|
self.client_disconnect,
|
||||||
);
|
);
|
||||||
H2Service::with_config(cfg, service.into_new_service())
|
H2Service::with_config(cfg, service.into_factory()).on_connect(self.on_connect)
|
||||||
.on_connect(self.on_connect)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finish service configuration and create `HttpService` instance.
|
/// Finish service configuration and create `HttpService` instance.
|
||||||
pub fn finish<F, P, B>(self, service: F) -> HttpService<T, P, S, B, X, U>
|
pub fn finish<F, P, B>(self, service: F) -> HttpService<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
F: IntoNewService<S>,
|
F: IntoServiceFactory<S>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
let cfg = ServiceConfig::new(
|
let cfg = ServiceConfig::new(
|
||||||
self.keep_alive,
|
self.keep_alive,
|
||||||
self.client_timeout,
|
self.client_timeout,
|
||||||
self.client_disconnect,
|
self.client_disconnect,
|
||||||
);
|
);
|
||||||
HttpService::with_config(cfg, service.into_new_service())
|
HttpService::with_config(cfg, service.into_factory())
|
||||||
.expect(self.expect)
|
.expect(self.expect)
|
||||||
.upgrade(self.upgrade)
|
.upgrade(self.upgrade)
|
||||||
.on_connect(self.on_connect)
|
.on_connect(self.on_connect)
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
use actix_connect::{
|
use actix_connect::{
|
||||||
default_connector, Connect as TcpConnect, Connection as TcpConnection,
|
default_connector, Connect as TcpConnect, Connection as TcpConnection,
|
||||||
};
|
};
|
||||||
use actix_service::{apply_fn, Service, ServiceExt};
|
use actix_service::{apply_fn, Service};
|
||||||
use actix_utils::timeout::{TimeoutError, TimeoutService};
|
use actix_utils::timeout::{TimeoutError, TimeoutService};
|
||||||
use http::Uri;
|
use http::Uri;
|
||||||
use tokio_tcp::TcpStream;
|
use tokio_net::tcp::TcpStream;
|
||||||
|
|
||||||
use super::connection::Connection;
|
use super::connection::Connection;
|
||||||
use super::error::ConnectError;
|
use super::error::ConnectError;
|
||||||
@ -212,7 +215,7 @@ where
|
|||||||
pub fn finish(
|
pub fn finish(
|
||||||
self,
|
self,
|
||||||
) -> impl Service<Request = Connect, Response = impl Connection, Error = ConnectError>
|
) -> impl Service<Request = Connect, Response = impl Connection, Error = ConnectError>
|
||||||
+ Clone {
|
+ Clone {
|
||||||
#[cfg(not(any(feature = "ssl", feature = "rust-tls")))]
|
#[cfg(not(any(feature = "ssl", feature = "rust-tls")))]
|
||||||
{
|
{
|
||||||
let connector = TimeoutService::new(
|
let connector = TimeoutService::new(
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
use std::future::Future;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::{io, time};
|
use std::{io, time};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
use bytes::{BufMut, Bytes, BytesMut};
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
use futures::future::{ok, Either};
|
use futures::future::{ok, Either};
|
||||||
use futures::{Async, Future, Poll, Sink, Stream};
|
use futures::{Sink, Stream};
|
||||||
|
|
||||||
use crate::error::PayloadError;
|
use crate::error::PayloadError;
|
||||||
use crate::h1;
|
use crate::h1;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::future::{err, Either};
|
use futures::future::{err, Either};
|
||||||
use futures::{Async, Future, Poll};
|
|
||||||
use h2::{client::SendRequest, SendStream};
|
use h2::{client::SendRequest, SendStream};
|
||||||
use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, TRANSFER_ENCODING};
|
use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, TRANSFER_ENCODING};
|
||||||
use http::{request::Request, HttpTryFrom, Method, Version};
|
use http::{request::Request, HttpTryFrom, Method, Version};
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::future::Future;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
|
use actix_utils::oneshot;
|
||||||
|
use actix_utils::task::LocalWaker;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::future::{err, ok, Either, FutureResult};
|
use futures::future::{err, ok, Either, FutureResult};
|
||||||
use futures::task::AtomicTask;
|
|
||||||
use futures::unsync::oneshot;
|
|
||||||
use futures::{Async, Future, Poll};
|
|
||||||
use h2::client::{handshake, Handshake};
|
use h2::client::{handshake, Handshake};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use http::uri::Authority;
|
use http::uri::Authority;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use tokio_timer::{sleep, Delay};
|
use tokio_timer::{delay_for, Delay};
|
||||||
|
|
||||||
use super::connection::{ConnectionType, IoConnection};
|
use super::connection::{ConnectionType, IoConnection};
|
||||||
use super::error::ConnectError;
|
use super::error::ConnectError;
|
||||||
@ -140,7 +142,7 @@ where
|
|||||||
// start support future
|
// start support future
|
||||||
if !support {
|
if !support {
|
||||||
self.1.as_ref().borrow_mut().task = Some(AtomicTask::new());
|
self.1.as_ref().borrow_mut().task = Some(AtomicTask::new());
|
||||||
tokio_current_thread::spawn(ConnectorPoolSupport {
|
tokio_executor::current_thread::spawn(ConnectorPoolSupport {
|
||||||
connector: self.0.clone(),
|
connector: self.0.clone(),
|
||||||
inner: self.1.clone(),
|
inner: self.1.clone(),
|
||||||
})
|
})
|
||||||
@ -255,7 +257,7 @@ where
|
|||||||
if let Some(ref mut h2) = self.h2 {
|
if let Some(ref mut h2) = self.h2 {
|
||||||
return match h2.poll() {
|
return match h2.poll() {
|
||||||
Ok(Async::Ready((snd, connection))) => {
|
Ok(Async::Ready((snd, connection))) => {
|
||||||
tokio_current_thread::spawn(connection.map_err(|_| ()));
|
tokio_executor::current_thread::spawn(connection.map_err(|_| ()));
|
||||||
Ok(Async::Ready(IoConnection::new(
|
Ok(Async::Ready(IoConnection::new(
|
||||||
ConnectionType::H2(snd),
|
ConnectionType::H2(snd),
|
||||||
Instant::now(),
|
Instant::now(),
|
||||||
@ -373,7 +375,7 @@ where
|
|||||||
{
|
{
|
||||||
if let Some(timeout) = self.disconnect_timeout {
|
if let Some(timeout) = self.disconnect_timeout {
|
||||||
if let ConnectionType::H1(io) = conn.io {
|
if let ConnectionType::H1(io) = conn.io {
|
||||||
tokio_current_thread::spawn(CloseConnection::new(
|
tokio_executor::current_thread::spawn(CloseConnection::new(
|
||||||
io, timeout,
|
io, timeout,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -387,7 +389,7 @@ where
|
|||||||
Ok(n) if n > 0 => {
|
Ok(n) if n > 0 => {
|
||||||
if let Some(timeout) = self.disconnect_timeout {
|
if let Some(timeout) = self.disconnect_timeout {
|
||||||
if let ConnectionType::H1(io) = io {
|
if let ConnectionType::H1(io) = io {
|
||||||
tokio_current_thread::spawn(
|
tokio_executor::current_thread::spawn(
|
||||||
CloseConnection::new(io, timeout),
|
CloseConnection::new(io, timeout),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -421,7 +423,7 @@ where
|
|||||||
self.acquired -= 1;
|
self.acquired -= 1;
|
||||||
if let Some(timeout) = self.disconnect_timeout {
|
if let Some(timeout) = self.disconnect_timeout {
|
||||||
if let ConnectionType::H1(io) = io {
|
if let ConnectionType::H1(io) = io {
|
||||||
tokio_current_thread::spawn(CloseConnection::new(io, timeout))
|
tokio_executor::current_thread::spawn(CloseConnection::new(io, timeout))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.check_availibility();
|
self.check_availibility();
|
||||||
@ -448,7 +450,7 @@ where
|
|||||||
fn new(io: T, timeout: Duration) -> Self {
|
fn new(io: T, timeout: Duration) -> Self {
|
||||||
CloseConnection {
|
CloseConnection {
|
||||||
io,
|
io,
|
||||||
timeout: sleep(timeout),
|
timeout: delay_for(timeout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,7 +560,7 @@ where
|
|||||||
inner: Rc<RefCell<Inner<Io>>>,
|
inner: Rc<RefCell<Inner<Io>>>,
|
||||||
fut: F,
|
fut: F,
|
||||||
) {
|
) {
|
||||||
tokio_current_thread::spawn(OpenWaitingConnection {
|
tokio_executor::current_thread::spawn(OpenWaitingConnection {
|
||||||
key,
|
key,
|
||||||
fut,
|
fut,
|
||||||
h2: None,
|
h2: None,
|
||||||
@ -593,7 +595,7 @@ where
|
|||||||
if let Some(ref mut h2) = self.h2 {
|
if let Some(ref mut h2) = self.h2 {
|
||||||
return match h2.poll() {
|
return match h2.poll() {
|
||||||
Ok(Async::Ready((snd, connection))) => {
|
Ok(Async::Ready((snd, connection))) => {
|
||||||
tokio_current_thread::spawn(connection.map_err(|_| ()));
|
tokio_executor::current_thread::spawn(connection.map_err(|_| ()));
|
||||||
let rx = self.rx.take().unwrap();
|
let rx = self.rx.take().unwrap();
|
||||||
let _ = rx.send(Ok(IoConnection::new(
|
let _ = rx.send(Ok(IoConnection::new(
|
||||||
ConnectionType::H2(snd),
|
ConnectionType::H2(snd),
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
use futures::Poll;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Service that allows to turn non-clone service to a service with `Clone` impl
|
/// Service that allows to turn non-clone service to a service with `Clone` impl
|
||||||
@ -32,8 +32,8 @@ where
|
|||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
type Future = T::Future;
|
type Future = T::Future;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
unsafe { &mut *self.0.as_ref().get() }.poll_ready()
|
unsafe { &mut *self.0.as_ref().get() }.poll_ready(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: T::Request) -> Self::Future {
|
fn call(&mut self, req: T::Request) -> Self::Future {
|
||||||
|
@ -5,9 +5,9 @@ use std::rc::Rc;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use futures::{future, Future};
|
use futures::{future, Future, FutureExt};
|
||||||
use time;
|
use time;
|
||||||
use tokio_timer::{sleep, Delay};
|
use tokio_timer::{delay, delay_for, Delay};
|
||||||
|
|
||||||
// "Sun, 06 Nov 1994 08:49:37 GMT".len()
|
// "Sun, 06 Nov 1994 08:49:37 GMT".len()
|
||||||
const DATE_VALUE_LENGTH: usize = 29;
|
const DATE_VALUE_LENGTH: usize = 29;
|
||||||
@ -104,10 +104,10 @@ impl ServiceConfig {
|
|||||||
#[inline]
|
#[inline]
|
||||||
/// Client timeout for first request.
|
/// Client timeout for first request.
|
||||||
pub fn client_timer(&self) -> Option<Delay> {
|
pub fn client_timer(&self) -> Option<Delay> {
|
||||||
let delay = self.0.client_timeout;
|
let delay_time = self.0.client_timeout;
|
||||||
if delay != 0 {
|
if delay_time != 0 {
|
||||||
Some(Delay::new(
|
Some(delay(
|
||||||
self.0.timer.now() + Duration::from_millis(delay),
|
self.0.timer.now() + Duration::from_millis(delay_time),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -138,7 +138,7 @@ impl ServiceConfig {
|
|||||||
/// Return keep-alive timer delay is configured.
|
/// Return keep-alive timer delay is configured.
|
||||||
pub fn keep_alive_timer(&self) -> Option<Delay> {
|
pub fn keep_alive_timer(&self) -> Option<Delay> {
|
||||||
if let Some(ka) = self.0.keep_alive {
|
if let Some(ka) = self.0.keep_alive {
|
||||||
Some(Delay::new(self.0.timer.now() + ka))
|
Some(delay(self.0.timer.now() + ka))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -242,12 +242,12 @@ impl DateService {
|
|||||||
|
|
||||||
// periodic date update
|
// periodic date update
|
||||||
let s = self.clone();
|
let s = self.clone();
|
||||||
tokio_current_thread::spawn(sleep(Duration::from_millis(500)).then(
|
tokio_executor::current_thread::spawn(
|
||||||
move |_| {
|
delay_for(Duration::from_millis(500)).then(move |_| {
|
||||||
s.0.reset();
|
s.0.reset();
|
||||||
future::ok(())
|
future::ready(())
|
||||||
},
|
}),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
use std::future::Future;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_threadpool::{run, CpuFuture};
|
use actix_threadpool::{run, CpuFuture};
|
||||||
#[cfg(feature = "brotli")]
|
#[cfg(feature = "brotli")]
|
||||||
@ -6,7 +9,7 @@ use brotli2::write::BrotliDecoder;
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||||
use flate2::write::{GzDecoder, ZlibDecoder};
|
use flate2::write::{GzDecoder, ZlibDecoder};
|
||||||
use futures::{try_ready, Async, Future, Poll, Stream};
|
use futures::{ready, Stream};
|
||||||
|
|
||||||
use super::Writer;
|
use super::Writer;
|
||||||
use crate::error::PayloadError;
|
use crate::error::PayloadError;
|
||||||
@ -18,12 +21,12 @@ pub struct Decoder<S> {
|
|||||||
decoder: Option<ContentDecoder>,
|
decoder: Option<ContentDecoder>,
|
||||||
stream: S,
|
stream: S,
|
||||||
eof: bool,
|
eof: bool,
|
||||||
fut: Option<CpuFuture<(Option<Bytes>, ContentDecoder), io::Error>>,
|
fut: Option<CpuFuture<Result<(Option<Bytes>, ContentDecoder), io::Error>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Decoder<S>
|
impl<S> Decoder<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
S: Stream<Item = Result<Bytes, PayloadError>>,
|
||||||
{
|
{
|
||||||
/// Construct a decoder.
|
/// Construct a decoder.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -71,34 +74,41 @@ where
|
|||||||
|
|
||||||
impl<S> Stream for Decoder<S>
|
impl<S> Stream for Decoder<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
S: Stream<Item = Result<Bytes, PayloadError>> + Unpin,
|
||||||
{
|
{
|
||||||
type Item = Bytes;
|
type Item = Result<Bytes, PayloadError>;
|
||||||
type Error = PayloadError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll_next(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Poll<Option<Self::Item>> {
|
||||||
loop {
|
loop {
|
||||||
if let Some(ref mut fut) = self.fut {
|
if let Some(ref mut fut) = self.fut {
|
||||||
let (chunk, decoder) = try_ready!(fut.poll());
|
let (chunk, decoder) = match ready!(Pin::new(fut).poll(cx)) {
|
||||||
|
Ok(Ok(item)) => item,
|
||||||
|
Ok(Err(e)) => return Poll::Ready(Some(Err(e.into()))),
|
||||||
|
Err(e) => return Poll::Ready(Some(Err(e.into()))),
|
||||||
|
};
|
||||||
self.decoder = Some(decoder);
|
self.decoder = Some(decoder);
|
||||||
self.fut.take();
|
self.fut.take();
|
||||||
if let Some(chunk) = chunk {
|
if let Some(chunk) = chunk {
|
||||||
return Ok(Async::Ready(Some(chunk)));
|
return Poll::Ready(Some(Ok(chunk)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.eof {
|
if self.eof {
|
||||||
return Ok(Async::Ready(None));
|
return Poll::Ready(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.stream.poll()? {
|
match Pin::new(&mut self.stream).poll_next(cx) {
|
||||||
Async::Ready(Some(chunk)) => {
|
Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(err))),
|
||||||
|
Poll::Ready(Some(Ok(chunk))) => {
|
||||||
if let Some(mut decoder) = self.decoder.take() {
|
if let Some(mut decoder) = self.decoder.take() {
|
||||||
if chunk.len() < INPLACE {
|
if chunk.len() < INPLACE {
|
||||||
let chunk = decoder.feed_data(chunk)?;
|
let chunk = decoder.feed_data(chunk)?;
|
||||||
self.decoder = Some(decoder);
|
self.decoder = Some(decoder);
|
||||||
if let Some(chunk) = chunk {
|
if let Some(chunk) = chunk {
|
||||||
return Ok(Async::Ready(Some(chunk)));
|
return Poll::Ready(Some(Ok(chunk)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.fut = Some(run(move || {
|
self.fut = Some(run(move || {
|
||||||
@ -108,21 +118,25 @@ where
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return Ok(Async::Ready(Some(chunk)));
|
return Poll::Ready(Some(Ok(chunk)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Async::Ready(None) => {
|
Poll::Ready(None) => {
|
||||||
self.eof = true;
|
self.eof = true;
|
||||||
return if let Some(mut decoder) = self.decoder.take() {
|
return if let Some(mut decoder) = self.decoder.take() {
|
||||||
Ok(Async::Ready(decoder.feed_eof()?))
|
match decoder.feed_eof() {
|
||||||
|
Ok(Some(res)) => Poll::Ready(Some(Ok(res))),
|
||||||
|
Ok(None) => Poll::Ready(None),
|
||||||
|
Err(err) => Poll::Ready(Some(Err(err.into()))),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Async::NotReady => break,
|
Poll::Pending => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady)
|
Poll::Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
//! Stream encoder
|
//! Stream encoder
|
||||||
|
use std::future::Future;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_threadpool::{run, CpuFuture};
|
use actix_threadpool::{run, CpuFuture};
|
||||||
#[cfg(feature = "brotli")]
|
#[cfg(feature = "brotli")]
|
||||||
@ -7,7 +10,6 @@ use brotli2::write::BrotliEncoder;
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||||
use flate2::write::{GzEncoder, ZlibEncoder};
|
use flate2::write::{GzEncoder, ZlibEncoder};
|
||||||
use futures::{Async, Future, Poll};
|
|
||||||
|
|
||||||
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
||||||
use crate::http::header::{ContentEncoding, CONTENT_ENCODING};
|
use crate::http::header::{ContentEncoding, CONTENT_ENCODING};
|
||||||
@ -22,7 +24,7 @@ pub struct Encoder<B> {
|
|||||||
eof: bool,
|
eof: bool,
|
||||||
body: EncoderBody<B>,
|
body: EncoderBody<B>,
|
||||||
encoder: Option<ContentEncoder>,
|
encoder: Option<ContentEncoder>,
|
||||||
fut: Option<CpuFuture<ContentEncoder, io::Error>>,
|
fut: Option<CpuFuture<Result<ContentEncoder, io::Error>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: MessageBody> Encoder<B> {
|
impl<B: MessageBody> Encoder<B> {
|
||||||
@ -94,43 +96,46 @@ impl<B: MessageBody> MessageBody for Encoder<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_next(&mut self) -> Poll<Option<Bytes>, Error> {
|
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
loop {
|
loop {
|
||||||
if self.eof {
|
if self.eof {
|
||||||
return Ok(Async::Ready(None));
|
return Poll::Ready(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut fut) = self.fut {
|
if let Some(ref mut fut) = self.fut {
|
||||||
let mut encoder = futures::try_ready!(fut.poll());
|
let mut encoder = match futures::ready!(Pin::new(fut).poll(cx)) {
|
||||||
|
Ok(Ok(item)) => item,
|
||||||
|
Ok(Err(e)) => return Poll::Ready(Some(Err(e.into()))),
|
||||||
|
Err(e) => return Poll::Ready(Some(Err(e.into()))),
|
||||||
|
};
|
||||||
let chunk = encoder.take();
|
let chunk = encoder.take();
|
||||||
self.encoder = Some(encoder);
|
self.encoder = Some(encoder);
|
||||||
self.fut.take();
|
self.fut.take();
|
||||||
if !chunk.is_empty() {
|
if !chunk.is_empty() {
|
||||||
return Ok(Async::Ready(Some(chunk)));
|
return Poll::Ready(Some(Ok(chunk)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = match self.body {
|
let result = match self.body {
|
||||||
EncoderBody::Bytes(ref mut b) => {
|
EncoderBody::Bytes(ref mut b) => {
|
||||||
if b.is_empty() {
|
if b.is_empty() {
|
||||||
Async::Ready(None)
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
Async::Ready(Some(std::mem::replace(b, Bytes::new())))
|
Poll::Ready(Some(Ok(std::mem::replace(b, Bytes::new()))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EncoderBody::Stream(ref mut b) => b.poll_next()?,
|
EncoderBody::Stream(ref mut b) => b.poll_next(cx),
|
||||||
EncoderBody::BoxedStream(ref mut b) => b.poll_next()?,
|
EncoderBody::BoxedStream(ref mut b) => b.poll_next(cx),
|
||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
Async::NotReady => return Ok(Async::NotReady),
|
Poll::Ready(Some(Ok(chunk))) => {
|
||||||
Async::Ready(Some(chunk)) => {
|
|
||||||
if let Some(mut encoder) = self.encoder.take() {
|
if let Some(mut encoder) = self.encoder.take() {
|
||||||
if chunk.len() < INPLACE {
|
if chunk.len() < INPLACE {
|
||||||
encoder.write(&chunk)?;
|
encoder.write(&chunk)?;
|
||||||
let chunk = encoder.take();
|
let chunk = encoder.take();
|
||||||
self.encoder = Some(encoder);
|
self.encoder = Some(encoder);
|
||||||
if !chunk.is_empty() {
|
if !chunk.is_empty() {
|
||||||
return Ok(Async::Ready(Some(chunk)));
|
return Poll::Ready(Some(Ok(chunk)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.fut = Some(run(move || {
|
self.fut = Some(run(move || {
|
||||||
@ -139,22 +144,23 @@ impl<B: MessageBody> MessageBody for Encoder<B> {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(Async::Ready(Some(chunk)));
|
return Poll::Ready(Some(Ok(chunk)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Async::Ready(None) => {
|
Poll::Ready(None) => {
|
||||||
if let Some(encoder) = self.encoder.take() {
|
if let Some(encoder) = self.encoder.take() {
|
||||||
let chunk = encoder.finish()?;
|
let chunk = encoder.finish()?;
|
||||||
if chunk.is_empty() {
|
if chunk.is_empty() {
|
||||||
return Ok(Async::Ready(None));
|
return Poll::Ready(None);
|
||||||
} else {
|
} else {
|
||||||
self.eof = true;
|
self.eof = true;
|
||||||
return Ok(Async::Ready(Some(chunk)));
|
return Poll::Ready(Some(Ok(chunk)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(Async::Ready(None));
|
return Poll::Ready(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val => return val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,10 @@ use std::str::Utf8Error;
|
|||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
use std::{fmt, io, result};
|
use std::{fmt, io, result};
|
||||||
|
|
||||||
pub use actix_threadpool::BlockingError;
|
|
||||||
use actix_utils::timeout::TimeoutError;
|
use actix_utils::timeout::TimeoutError;
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use derive_more::{Display, From};
|
use derive_more::{Display, From};
|
||||||
use futures::Canceled;
|
use futures::channel::oneshot::Canceled;
|
||||||
use http::uri::InvalidUri;
|
use http::uri::InvalidUri;
|
||||||
use http::{header, Error as HttpError, StatusCode};
|
use http::{header, Error as HttpError, StatusCode};
|
||||||
use httparse;
|
use httparse;
|
||||||
@ -197,8 +196,8 @@ impl ResponseError for DeError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `InternalServerError` for `BlockingError`
|
/// `InternalServerError` for `Canceled`
|
||||||
impl<E: fmt::Debug> ResponseError for BlockingError<E> {}
|
impl ResponseError for Canceled {}
|
||||||
|
|
||||||
/// Return `BAD_REQUEST` for `Utf8Error`
|
/// Return `BAD_REQUEST` for `Utf8Error`
|
||||||
impl ResponseError for Utf8Error {
|
impl ResponseError for Utf8Error {
|
||||||
@ -236,9 +235,6 @@ impl ResponseError for header::InvalidHeaderValueBytes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `InternalServerError` for `futures::Canceled`
|
|
||||||
impl ResponseError for Canceled {}
|
|
||||||
|
|
||||||
/// A set of errors that can occur during parsing HTTP streams
|
/// A set of errors that can occur during parsing HTTP streams
|
||||||
#[derive(Debug, Display)]
|
#[derive(Debug, Display)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
@ -365,15 +361,12 @@ impl From<io::Error> for PayloadError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BlockingError<io::Error>> for PayloadError {
|
impl From<Canceled> for PayloadError {
|
||||||
fn from(err: BlockingError<io::Error>) -> Self {
|
fn from(_: Canceled) -> Self {
|
||||||
match err {
|
PayloadError::Io(io::Error::new(
|
||||||
BlockingError::Error(e) => PayloadError::Io(e),
|
io::ErrorKind::Other,
|
||||||
BlockingError::Canceled => PayloadError::Io(io::Error::new(
|
"Operation is canceled",
|
||||||
io::ErrorKind::Other,
|
))
|
||||||
"Thread pool is gone",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,12 +383,12 @@ impl ResponseError for PayloadError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `BadRequest` for `cookie::ParseError`
|
// /// Return `BadRequest` for `cookie::ParseError`
|
||||||
impl ResponseError for crate::cookie::ParseError {
|
// impl ResponseError for crate::cookie::ParseError {
|
||||||
fn error_response(&self) -> Response {
|
// fn error_response(&self) -> Response {
|
||||||
Response::new(StatusCode::BAD_REQUEST)
|
// Response::new(StatusCode::BAD_REQUEST)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Display, From)]
|
#[derive(Debug, Display, From)]
|
||||||
/// A set of errors that can occur during dispatching http requests
|
/// A set of errors that can occur during dispatching http requests
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
use std::future::Future;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_codec::Decoder;
|
use actix_codec::Decoder;
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures::{Async, Poll};
|
|
||||||
use http::header::{HeaderName, HeaderValue};
|
use http::header::{HeaderName, HeaderValue};
|
||||||
use http::{header, HttpTryFrom, Method, StatusCode, Uri, Version};
|
use http::{header, HttpTryFrom, Method, StatusCode, Uri, Version};
|
||||||
use httparse;
|
use httparse;
|
||||||
@ -442,9 +444,10 @@ impl Decoder for PayloadDecoder {
|
|||||||
loop {
|
loop {
|
||||||
let mut buf = None;
|
let mut buf = None;
|
||||||
// advances the chunked state
|
// advances the chunked state
|
||||||
*state = match state.step(src, size, &mut buf)? {
|
*state = match state.step(src, size, &mut buf) {
|
||||||
Async::NotReady => return Ok(None),
|
Poll::Pending => return Ok(None),
|
||||||
Async::Ready(state) => state,
|
Poll::Ready(Ok(state)) => state,
|
||||||
|
Poll::Ready(Err(e)) => return Err(e),
|
||||||
};
|
};
|
||||||
if *state == ChunkedState::End {
|
if *state == ChunkedState::End {
|
||||||
trace!("End of chunked stream");
|
trace!("End of chunked stream");
|
||||||
@ -476,7 +479,7 @@ macro_rules! byte (
|
|||||||
$rdr.split_to(1);
|
$rdr.split_to(1);
|
||||||
b
|
b
|
||||||
} else {
|
} else {
|
||||||
return Ok(Async::NotReady)
|
return Poll::Pending
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -487,7 +490,7 @@ impl ChunkedState {
|
|||||||
body: &mut BytesMut,
|
body: &mut BytesMut,
|
||||||
size: &mut u64,
|
size: &mut u64,
|
||||||
buf: &mut Option<Bytes>,
|
buf: &mut Option<Bytes>,
|
||||||
) -> Poll<ChunkedState, io::Error> {
|
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
use self::ChunkedState::*;
|
use self::ChunkedState::*;
|
||||||
match *self {
|
match *self {
|
||||||
Size => ChunkedState::read_size(body, size),
|
Size => ChunkedState::read_size(body, size),
|
||||||
@ -499,10 +502,14 @@ impl ChunkedState {
|
|||||||
BodyLf => ChunkedState::read_body_lf(body),
|
BodyLf => ChunkedState::read_body_lf(body),
|
||||||
EndCr => ChunkedState::read_end_cr(body),
|
EndCr => ChunkedState::read_end_cr(body),
|
||||||
EndLf => ChunkedState::read_end_lf(body),
|
EndLf => ChunkedState::read_end_lf(body),
|
||||||
End => Ok(Async::Ready(ChunkedState::End)),
|
End => Poll::Ready(Ok(ChunkedState::End)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_size(rdr: &mut BytesMut, size: &mut u64) -> Poll<ChunkedState, io::Error> {
|
|
||||||
|
fn read_size(
|
||||||
|
rdr: &mut BytesMut,
|
||||||
|
size: &mut u64,
|
||||||
|
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
let radix = 16;
|
let radix = 16;
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b @ b'0'..=b'9' => {
|
b @ b'0'..=b'9' => {
|
||||||
@ -517,48 +524,49 @@ impl ChunkedState {
|
|||||||
*size *= radix;
|
*size *= radix;
|
||||||
*size += u64::from(b + 10 - b'A');
|
*size += u64::from(b + 10 - b'A');
|
||||||
}
|
}
|
||||||
b'\t' | b' ' => return Ok(Async::Ready(ChunkedState::SizeLws)),
|
b'\t' | b' ' => return Poll::Ready(Ok(ChunkedState::SizeLws)),
|
||||||
b';' => return Ok(Async::Ready(ChunkedState::Extension)),
|
b';' => return Poll::Ready(Ok(ChunkedState::Extension)),
|
||||||
b'\r' => return Ok(Async::Ready(ChunkedState::SizeLf)),
|
b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(io::Error::new(
|
return Poll::Ready(Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"Invalid chunk size line: Invalid Size",
|
"Invalid chunk size line: Invalid Size",
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(ChunkedState::Size))
|
Poll::Ready(Ok(ChunkedState::Size))
|
||||||
}
|
}
|
||||||
fn read_size_lws(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
|
||||||
|
fn read_size_lws(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
trace!("read_size_lws");
|
trace!("read_size_lws");
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
// LWS can follow the chunk size, but no more digits can come
|
// LWS can follow the chunk size, but no more digits can come
|
||||||
b'\t' | b' ' => Ok(Async::Ready(ChunkedState::SizeLws)),
|
b'\t' | b' ' => Poll::Ready(Ok(ChunkedState::SizeLws)),
|
||||||
b';' => Ok(Async::Ready(ChunkedState::Extension)),
|
b';' => Poll::Ready(Ok(ChunkedState::Extension)),
|
||||||
b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)),
|
b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||||
_ => Err(io::Error::new(
|
_ => Poll::Ready(Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"Invalid chunk size linear white space",
|
"Invalid chunk size linear white space",
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_extension(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
fn read_extension(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)),
|
b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||||
_ => Ok(Async::Ready(ChunkedState::Extension)), // no supported extensions
|
_ => Poll::Ready(Ok(ChunkedState::Extension)), // no supported extensions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_size_lf(
|
fn read_size_lf(
|
||||||
rdr: &mut BytesMut,
|
rdr: &mut BytesMut,
|
||||||
size: &mut u64,
|
size: &mut u64,
|
||||||
) -> Poll<ChunkedState, io::Error> {
|
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)),
|
b'\n' if *size > 0 => Poll::Ready(Ok(ChunkedState::Body)),
|
||||||
b'\n' if *size == 0 => Ok(Async::Ready(ChunkedState::EndCr)),
|
b'\n' if *size == 0 => Poll::Ready(Ok(ChunkedState::EndCr)),
|
||||||
_ => Err(io::Error::new(
|
_ => Poll::Ready(Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"Invalid chunk size LF",
|
"Invalid chunk size LF",
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,12 +574,12 @@ impl ChunkedState {
|
|||||||
rdr: &mut BytesMut,
|
rdr: &mut BytesMut,
|
||||||
rem: &mut u64,
|
rem: &mut u64,
|
||||||
buf: &mut Option<Bytes>,
|
buf: &mut Option<Bytes>,
|
||||||
) -> Poll<ChunkedState, io::Error> {
|
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
trace!("Chunked read, remaining={:?}", rem);
|
trace!("Chunked read, remaining={:?}", rem);
|
||||||
|
|
||||||
let len = rdr.len() as u64;
|
let len = rdr.len() as u64;
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
Ok(Async::Ready(ChunkedState::Body))
|
Poll::Ready(Ok(ChunkedState::Body))
|
||||||
} else {
|
} else {
|
||||||
let slice;
|
let slice;
|
||||||
if *rem > len {
|
if *rem > len {
|
||||||
@ -583,47 +591,47 @@ impl ChunkedState {
|
|||||||
}
|
}
|
||||||
*buf = Some(slice);
|
*buf = Some(slice);
|
||||||
if *rem > 0 {
|
if *rem > 0 {
|
||||||
Ok(Async::Ready(ChunkedState::Body))
|
Poll::Ready(Ok(ChunkedState::Body))
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(ChunkedState::BodyCr))
|
Poll::Ready(Ok(ChunkedState::BodyCr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_body_cr(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
fn read_body_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\r' => Ok(Async::Ready(ChunkedState::BodyLf)),
|
b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)),
|
||||||
_ => Err(io::Error::new(
|
_ => Poll::Ready(Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"Invalid chunk body CR",
|
"Invalid chunk body CR",
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_body_lf(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
fn read_body_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\n' => Ok(Async::Ready(ChunkedState::Size)),
|
b'\n' => Poll::Ready(Ok(ChunkedState::Size)),
|
||||||
_ => Err(io::Error::new(
|
_ => Poll::Ready(Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"Invalid chunk body LF",
|
"Invalid chunk body LF",
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_end_cr(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
fn read_end_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\r' => Ok(Async::Ready(ChunkedState::EndLf)),
|
b'\r' => Poll::Ready(Ok(ChunkedState::EndLf)),
|
||||||
_ => Err(io::Error::new(
|
_ => Poll::Ready(Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"Invalid chunk end CR",
|
"Invalid chunk end CR",
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn read_end_lf(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
fn read_end_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||||
match byte!(rdr) {
|
match byte!(rdr) {
|
||||||
b'\n' => Ok(Async::Ready(ChunkedState::End)),
|
b'\n' => Poll::Ready(Ok(ChunkedState::End)),
|
||||||
_ => Err(io::Error::new(
|
_ => Poll::Ready(Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"Invalid chunk end LF",
|
"Invalid chunk end LF",
|
||||||
)),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::{fmt, io, net};
|
use std::{fmt, io, io::Write, net};
|
||||||
|
|
||||||
use actix_codec::{Decoder, Encoder, Framed, FramedParts};
|
use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts};
|
||||||
use actix_server_config::IoStream;
|
use actix_server_config::IoStream;
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use futures::{Async, Future, Poll};
|
|
||||||
use log::{error, trace};
|
use log::{error, trace};
|
||||||
use tokio_timer::Delay;
|
use tokio_timer::{delay, Delay};
|
||||||
|
|
||||||
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
||||||
use crate::cloneable::CloneableService;
|
use crate::cloneable::CloneableService;
|
||||||
@ -46,11 +48,14 @@ pub struct Dispatcher<T, S, B, X, U>
|
|||||||
where
|
where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
|
X::Future: Unpin,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
inner: DispatcherState<T, S, B, X, U>,
|
inner: DispatcherState<T, S, B, X, U>,
|
||||||
}
|
}
|
||||||
@ -59,11 +64,14 @@ enum DispatcherState<T, S, B, X, U>
|
|||||||
where
|
where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
|
X::Future: Unpin,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
Normal(InnerDispatcher<T, S, B, X, U>),
|
Normal(InnerDispatcher<T, S, B, X, U>),
|
||||||
Upgrade(U::Future),
|
Upgrade(U::Future),
|
||||||
@ -74,11 +82,14 @@ struct InnerDispatcher<T, S, B, X, U>
|
|||||||
where
|
where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
|
X::Future: Unpin,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
service: CloneableService<S>,
|
service: CloneableService<S>,
|
||||||
expect: CloneableService<X>,
|
expect: CloneableService<X>,
|
||||||
@ -170,11 +181,14 @@ where
|
|||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
|
X::Future: Unpin,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
/// Create http/1 dispatcher.
|
/// Create http/1 dispatcher.
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
@ -255,20 +269,23 @@ where
|
|||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
|
X::Future: Unpin,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
fn can_read(&self) -> bool {
|
fn can_read(&self, cx: &mut Context) -> bool {
|
||||||
if self
|
if self
|
||||||
.flags
|
.flags
|
||||||
.intersects(Flags::READ_DISCONNECT | Flags::UPGRADE)
|
.intersects(Flags::READ_DISCONNECT | Flags::UPGRADE)
|
||||||
{
|
{
|
||||||
false
|
false
|
||||||
} else if let Some(ref info) = self.payload {
|
} else if let Some(ref info) = self.payload {
|
||||||
info.need_read() == PayloadStatus::Read
|
info.need_read(cx) == PayloadStatus::Read
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -287,7 +304,7 @@ where
|
|||||||
///
|
///
|
||||||
/// true - got whouldblock
|
/// true - got whouldblock
|
||||||
/// false - didnt get whouldblock
|
/// false - didnt get whouldblock
|
||||||
fn poll_flush(&mut self) -> Result<bool, DispatchError> {
|
fn poll_flush(&mut self, cx: &mut Context) -> Result<bool, DispatchError> {
|
||||||
if self.write_buf.is_empty() {
|
if self.write_buf.is_empty() {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
@ -295,23 +312,23 @@ where
|
|||||||
let len = self.write_buf.len();
|
let len = self.write_buf.len();
|
||||||
let mut written = 0;
|
let mut written = 0;
|
||||||
while written < len {
|
while written < len {
|
||||||
match self.io.write(&self.write_buf[written..]) {
|
match Pin::new(&mut self.io).poll_write(cx, &self.write_buf[written..]) {
|
||||||
Ok(0) => {
|
Poll::Ready(Ok(0)) => {
|
||||||
return Err(DispatchError::Io(io::Error::new(
|
return Err(DispatchError::Io(io::Error::new(
|
||||||
io::ErrorKind::WriteZero,
|
io::ErrorKind::WriteZero,
|
||||||
"",
|
"",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Ok(n) => {
|
Poll::Ready(Ok(n)) => {
|
||||||
written += n;
|
written += n;
|
||||||
}
|
}
|
||||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
|
Poll::Pending => {
|
||||||
if written > 0 {
|
if written > 0 {
|
||||||
let _ = self.write_buf.split_to(written);
|
let _ = self.write_buf.split_to(written);
|
||||||
}
|
}
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
Err(err) => return Err(DispatchError::Io(err)),
|
Poll::Ready(Err(err)) => return Err(DispatchError::Io(err)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if written > 0 {
|
if written > 0 {
|
||||||
@ -350,12 +367,15 @@ where
|
|||||||
.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
|
.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_response(&mut self) -> Result<PollResponse, DispatchError> {
|
fn poll_response(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Result<PollResponse, DispatchError> {
|
||||||
loop {
|
loop {
|
||||||
let state = match self.state {
|
let state = match self.state {
|
||||||
State::None => match self.messages.pop_front() {
|
State::None => match self.messages.pop_front() {
|
||||||
Some(DispatcherMessage::Item(req)) => {
|
Some(DispatcherMessage::Item(req)) => {
|
||||||
Some(self.handle_request(req)?)
|
Some(self.handle_request(req, cx)?)
|
||||||
}
|
}
|
||||||
Some(DispatcherMessage::Error(res)) => {
|
Some(DispatcherMessage::Error(res)) => {
|
||||||
Some(self.send_response(res, ResponseBody::Other(Body::Empty))?)
|
Some(self.send_response(res, ResponseBody::Other(Body::Empty))?)
|
||||||
@ -365,54 +385,54 @@ where
|
|||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
},
|
},
|
||||||
State::ExpectCall(ref mut fut) => match fut.poll() {
|
State::ExpectCall(ref mut fut) => match Pin::new(fut).poll(cx) {
|
||||||
Ok(Async::Ready(req)) => {
|
Poll::Ready(Ok(req)) => {
|
||||||
self.send_continue();
|
self.send_continue();
|
||||||
self.state = State::ServiceCall(self.service.call(req));
|
self.state = State::ServiceCall(self.service.call(req));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady) => None,
|
Poll::Ready(Err(e)) => {
|
||||||
Err(e) => {
|
|
||||||
let res: Response = e.into().into();
|
let res: Response = e.into().into();
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
Some(self.send_response(res, body.into_body())?)
|
Some(self.send_response(res, body.into_body())?)
|
||||||
}
|
}
|
||||||
|
Poll::Pending => None,
|
||||||
},
|
},
|
||||||
State::ServiceCall(ref mut fut) => match fut.poll() {
|
State::ServiceCall(ref mut fut) => match Pin::new(fut).poll(cx) {
|
||||||
Ok(Async::Ready(res)) => {
|
Poll::Ready(Ok(res)) => {
|
||||||
let (res, body) = res.into().replace_body(());
|
let (res, body) = res.into().replace_body(());
|
||||||
self.state = self.send_response(res, body)?;
|
self.state = self.send_response(res, body)?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady) => None,
|
Poll::Ready(Err(e)) => {
|
||||||
Err(e) => {
|
|
||||||
let res: Response = e.into().into();
|
let res: Response = e.into().into();
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
Some(self.send_response(res, body.into_body())?)
|
Some(self.send_response(res, body.into_body())?)
|
||||||
}
|
}
|
||||||
|
Poll::Pending => None,
|
||||||
},
|
},
|
||||||
State::SendPayload(ref mut stream) => {
|
State::SendPayload(ref mut stream) => {
|
||||||
loop {
|
loop {
|
||||||
if self.write_buf.len() < HW_BUFFER_SIZE {
|
if self.write_buf.len() < HW_BUFFER_SIZE {
|
||||||
match stream
|
match stream.poll_next(cx) {
|
||||||
.poll_next()
|
Poll::Ready(Some(Ok(item))) => {
|
||||||
.map_err(|_| DispatchError::Unknown)?
|
|
||||||
{
|
|
||||||
Async::Ready(Some(item)) => {
|
|
||||||
self.codec.encode(
|
self.codec.encode(
|
||||||
Message::Chunk(Some(item)),
|
Message::Chunk(Some(item)),
|
||||||
&mut self.write_buf,
|
&mut self.write_buf,
|
||||||
)?;
|
)?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Async::Ready(None) => {
|
Poll::Ready(None) => {
|
||||||
self.codec.encode(
|
self.codec.encode(
|
||||||
Message::Chunk(None),
|
Message::Chunk(None),
|
||||||
&mut self.write_buf,
|
&mut self.write_buf,
|
||||||
)?;
|
)?;
|
||||||
self.state = State::None;
|
self.state = State::None;
|
||||||
}
|
}
|
||||||
Async::NotReady => return Ok(PollResponse::DoNothing),
|
Poll::Ready(Some(Err(_))) => {
|
||||||
|
return Err(DispatchError::Unknown)
|
||||||
|
}
|
||||||
|
Poll::Pending => return Ok(PollResponse::DoNothing),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(PollResponse::DrainWriteBuf);
|
return Ok(PollResponse::DrainWriteBuf);
|
||||||
@ -433,7 +453,7 @@ where
|
|||||||
// if read-backpressure is enabled and we consumed some data.
|
// if read-backpressure is enabled and we consumed some data.
|
||||||
// we may read more data and retry
|
// we may read more data and retry
|
||||||
if self.state.is_call() {
|
if self.state.is_call() {
|
||||||
if self.poll_request()? {
|
if self.poll_request(cx)? {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if !self.messages.is_empty() {
|
} else if !self.messages.is_empty() {
|
||||||
@ -446,17 +466,21 @@ where
|
|||||||
Ok(PollResponse::DoNothing)
|
Ok(PollResponse::DoNothing)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_request(&mut self, req: Request) -> Result<State<S, B, X>, DispatchError> {
|
fn handle_request(
|
||||||
|
&mut self,
|
||||||
|
req: Request,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Result<State<S, B, X>, DispatchError> {
|
||||||
// Handle `EXPECT: 100-Continue` header
|
// Handle `EXPECT: 100-Continue` header
|
||||||
let req = if req.head().expect() {
|
let req = if req.head().expect() {
|
||||||
let mut task = self.expect.call(req);
|
let mut task = self.expect.call(req);
|
||||||
match task.poll() {
|
match Pin::new(&mut task).poll(cx) {
|
||||||
Ok(Async::Ready(req)) => {
|
Poll::Ready(Ok(req)) => {
|
||||||
self.send_continue();
|
self.send_continue();
|
||||||
req
|
req
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady) => return Ok(State::ExpectCall(task)),
|
Poll::Pending => return Ok(State::ExpectCall(task)),
|
||||||
Err(e) => {
|
Poll::Ready(Err(e)) => {
|
||||||
let e = e.into();
|
let e = e.into();
|
||||||
let res: Response = e.into();
|
let res: Response = e.into();
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
@ -469,13 +493,13 @@ where
|
|||||||
|
|
||||||
// Call service
|
// Call service
|
||||||
let mut task = self.service.call(req);
|
let mut task = self.service.call(req);
|
||||||
match task.poll() {
|
match Pin::new(&mut task).poll(cx) {
|
||||||
Ok(Async::Ready(res)) => {
|
Poll::Ready(Ok(res)) => {
|
||||||
let (res, body) = res.into().replace_body(());
|
let (res, body) = res.into().replace_body(());
|
||||||
self.send_response(res, body)
|
self.send_response(res, body)
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady) => Ok(State::ServiceCall(task)),
|
Poll::Pending => Ok(State::ServiceCall(task)),
|
||||||
Err(e) => {
|
Poll::Ready(Err(e)) => {
|
||||||
let res: Response = e.into().into();
|
let res: Response = e.into().into();
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
self.send_response(res, body.into_body())
|
self.send_response(res, body.into_body())
|
||||||
@ -484,9 +508,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Process one incoming requests
|
/// Process one incoming requests
|
||||||
pub(self) fn poll_request(&mut self) -> Result<bool, DispatchError> {
|
pub(self) fn poll_request(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Result<bool, DispatchError> {
|
||||||
// limit a mount of non processed requests
|
// limit a mount of non processed requests
|
||||||
if self.messages.len() >= MAX_PIPELINED_MESSAGES || !self.can_read() {
|
if self.messages.len() >= MAX_PIPELINED_MESSAGES || !self.can_read(cx) {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +548,7 @@ where
|
|||||||
|
|
||||||
// handle request early
|
// handle request early
|
||||||
if self.state.is_empty() {
|
if self.state.is_empty() {
|
||||||
self.state = self.handle_request(req)?;
|
self.state = self.handle_request(req, cx)?;
|
||||||
} else {
|
} else {
|
||||||
self.messages.push_back(DispatcherMessage::Item(req));
|
self.messages.push_back(DispatcherMessage::Item(req));
|
||||||
}
|
}
|
||||||
@ -587,12 +614,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// keep-alive timer
|
/// keep-alive timer
|
||||||
fn poll_keepalive(&mut self) -> Result<(), DispatchError> {
|
fn poll_keepalive(&mut self, cx: &mut Context) -> Result<(), DispatchError> {
|
||||||
if self.ka_timer.is_none() {
|
if self.ka_timer.is_none() {
|
||||||
// shutdown timeout
|
// shutdown timeout
|
||||||
if self.flags.contains(Flags::SHUTDOWN) {
|
if self.flags.contains(Flags::SHUTDOWN) {
|
||||||
if let Some(interval) = self.codec.config().client_disconnect_timer() {
|
if let Some(interval) = self.codec.config().client_disconnect_timer() {
|
||||||
self.ka_timer = Some(Delay::new(interval));
|
self.ka_timer = Some(delay(interval));
|
||||||
} else {
|
} else {
|
||||||
self.flags.insert(Flags::READ_DISCONNECT);
|
self.flags.insert(Flags::READ_DISCONNECT);
|
||||||
if let Some(mut payload) = self.payload.take() {
|
if let Some(mut payload) = self.payload.take() {
|
||||||
@ -605,11 +632,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.ka_timer.as_mut().unwrap().poll().map_err(|e| {
|
match Pin::new(&mut self.ka_timer.as_mut().unwrap()).poll(cx) {
|
||||||
error!("Timer error {:?}", e);
|
Poll::Ready(()) => {
|
||||||
DispatchError::Unknown
|
|
||||||
})? {
|
|
||||||
Async::Ready(_) => {
|
|
||||||
// if we get timeout during shutdown, drop connection
|
// if we get timeout during shutdown, drop connection
|
||||||
if self.flags.contains(Flags::SHUTDOWN) {
|
if self.flags.contains(Flags::SHUTDOWN) {
|
||||||
return Err(DispatchError::DisconnectTimeout);
|
return Err(DispatchError::DisconnectTimeout);
|
||||||
@ -624,9 +648,9 @@ where
|
|||||||
if let Some(deadline) =
|
if let Some(deadline) =
|
||||||
self.codec.config().client_disconnect_timer()
|
self.codec.config().client_disconnect_timer()
|
||||||
{
|
{
|
||||||
if let Some(timer) = self.ka_timer.as_mut() {
|
if let Some(mut timer) = self.ka_timer.as_mut() {
|
||||||
timer.reset(deadline);
|
timer.reset(deadline);
|
||||||
let _ = timer.poll();
|
let _ = Pin::new(&mut timer).poll(cx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no shutdown timeout, drop socket
|
// no shutdown timeout, drop socket
|
||||||
@ -650,17 +674,17 @@ where
|
|||||||
} else if let Some(deadline) =
|
} else if let Some(deadline) =
|
||||||
self.codec.config().keep_alive_expire()
|
self.codec.config().keep_alive_expire()
|
||||||
{
|
{
|
||||||
if let Some(timer) = self.ka_timer.as_mut() {
|
if let Some(mut timer) = self.ka_timer.as_mut() {
|
||||||
timer.reset(deadline);
|
timer.reset(deadline);
|
||||||
let _ = timer.poll();
|
let _ = Pin::new(&mut timer).poll(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(timer) = self.ka_timer.as_mut() {
|
} else if let Some(mut timer) = self.ka_timer.as_mut() {
|
||||||
timer.reset(self.ka_expire);
|
timer.reset(self.ka_expire);
|
||||||
let _ = timer.poll();
|
let _ = Pin::new(&mut timer).poll(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Async::NotReady => (),
|
Poll::Pending => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -673,33 +697,37 @@ where
|
|||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
|
X::Future: Unpin,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
type Item = ();
|
type Output = Result<(), DispatchError>;
|
||||||
type Error = DispatchError;
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
DispatcherState::Normal(ref mut inner) => {
|
DispatcherState::Normal(ref mut inner) => {
|
||||||
inner.poll_keepalive()?;
|
inner.poll_keepalive(cx)?;
|
||||||
|
|
||||||
if inner.flags.contains(Flags::SHUTDOWN) {
|
if inner.flags.contains(Flags::SHUTDOWN) {
|
||||||
if inner.flags.contains(Flags::WRITE_DISCONNECT) {
|
if inner.flags.contains(Flags::WRITE_DISCONNECT) {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(Ok(()))
|
||||||
} else {
|
} else {
|
||||||
// flush buffer
|
// flush buffer
|
||||||
inner.poll_flush()?;
|
inner.poll_flush(cx)?;
|
||||||
if !inner.write_buf.is_empty() {
|
if !inner.write_buf.is_empty() {
|
||||||
Ok(Async::NotReady)
|
Poll::Pending
|
||||||
} else {
|
} else {
|
||||||
match inner.io.shutdown()? {
|
match Pin::new(&mut inner.io).poll_shutdown(cx) {
|
||||||
Async::Ready(_) => Ok(Async::Ready(())),
|
Poll::Ready(res) => {
|
||||||
Async::NotReady => Ok(Async::NotReady),
|
Poll::Ready(res.map_err(DispatchError::from))
|
||||||
|
}
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -707,12 +735,12 @@ where
|
|||||||
// read socket into a buf
|
// read socket into a buf
|
||||||
let should_disconnect =
|
let should_disconnect =
|
||||||
if !inner.flags.contains(Flags::READ_DISCONNECT) {
|
if !inner.flags.contains(Flags::READ_DISCONNECT) {
|
||||||
read_available(&mut inner.io, &mut inner.read_buf)?
|
read_available(cx, &mut inner.io, &mut inner.read_buf)?
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
inner.poll_request()?;
|
inner.poll_request(cx)?;
|
||||||
if let Some(true) = should_disconnect {
|
if let Some(true) = should_disconnect {
|
||||||
inner.flags.insert(Flags::READ_DISCONNECT);
|
inner.flags.insert(Flags::READ_DISCONNECT);
|
||||||
if let Some(mut payload) = inner.payload.take() {
|
if let Some(mut payload) = inner.payload.take() {
|
||||||
@ -724,7 +752,7 @@ where
|
|||||||
if inner.write_buf.remaining_mut() < LW_BUFFER_SIZE {
|
if inner.write_buf.remaining_mut() < LW_BUFFER_SIZE {
|
||||||
inner.write_buf.reserve(HW_BUFFER_SIZE);
|
inner.write_buf.reserve(HW_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
let result = inner.poll_response()?;
|
let result = inner.poll_response(cx)?;
|
||||||
let drain = result == PollResponse::DrainWriteBuf;
|
let drain = result == PollResponse::DrainWriteBuf;
|
||||||
|
|
||||||
// switch to upgrade handler
|
// switch to upgrade handler
|
||||||
@ -742,7 +770,7 @@ where
|
|||||||
self.inner = DispatcherState::Upgrade(
|
self.inner = DispatcherState::Upgrade(
|
||||||
inner.upgrade.unwrap().call((req, framed)),
|
inner.upgrade.unwrap().call((req, framed)),
|
||||||
);
|
);
|
||||||
return self.poll();
|
return self.poll(cx);
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
@ -751,14 +779,14 @@ where
|
|||||||
// we didnt get WouldBlock from write operation,
|
// we didnt get WouldBlock from write operation,
|
||||||
// so data get written to kernel completely (OSX)
|
// so data get written to kernel completely (OSX)
|
||||||
// and we have to write again otherwise response can get stuck
|
// and we have to write again otherwise response can get stuck
|
||||||
if inner.poll_flush()? || !drain {
|
if inner.poll_flush(cx)? || !drain {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// client is gone
|
// client is gone
|
||||||
if inner.flags.contains(Flags::WRITE_DISCONNECT) {
|
if inner.flags.contains(Flags::WRITE_DISCONNECT) {
|
||||||
return Ok(Async::Ready(()));
|
return Poll::Ready(Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_empty = inner.state.is_empty();
|
let is_empty = inner.state.is_empty();
|
||||||
@ -771,38 +799,44 @@ where
|
|||||||
// keep-alive and stream errors
|
// keep-alive and stream errors
|
||||||
if is_empty && inner.write_buf.is_empty() {
|
if is_empty && inner.write_buf.is_empty() {
|
||||||
if let Some(err) = inner.error.take() {
|
if let Some(err) = inner.error.take() {
|
||||||
Err(err)
|
Poll::Ready(Err(err))
|
||||||
}
|
}
|
||||||
// disconnect if keep-alive is not enabled
|
// disconnect if keep-alive is not enabled
|
||||||
else if inner.flags.contains(Flags::STARTED)
|
else if inner.flags.contains(Flags::STARTED)
|
||||||
&& !inner.flags.intersects(Flags::KEEPALIVE)
|
&& !inner.flags.intersects(Flags::KEEPALIVE)
|
||||||
{
|
{
|
||||||
inner.flags.insert(Flags::SHUTDOWN);
|
inner.flags.insert(Flags::SHUTDOWN);
|
||||||
self.poll()
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
// disconnect if shutdown
|
// disconnect if shutdown
|
||||||
else if inner.flags.contains(Flags::SHUTDOWN) {
|
else if inner.flags.contains(Flags::SHUTDOWN) {
|
||||||
self.poll()
|
self.poll(cx)
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::NotReady)
|
Poll::Pending
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::NotReady)
|
Poll::Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DispatcherState::Upgrade(ref mut fut) => fut.poll().map_err(|e| {
|
DispatcherState::Upgrade(ref mut fut) => {
|
||||||
error!("Upgrade handler error: {}", e);
|
Pin::new(fut).poll(cx).map_err(|e| {
|
||||||
DispatchError::Upgrade
|
error!("Upgrade handler error: {}", e);
|
||||||
}),
|
DispatchError::Upgrade
|
||||||
|
})
|
||||||
|
}
|
||||||
DispatcherState::None => panic!(),
|
DispatcherState::None => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_available<T>(io: &mut T, buf: &mut BytesMut) -> Result<Option<bool>, io::Error>
|
fn read_available<T>(
|
||||||
|
cx: &mut Context,
|
||||||
|
io: &mut T,
|
||||||
|
buf: &mut BytesMut,
|
||||||
|
) -> Result<Option<bool>, io::Error>
|
||||||
where
|
where
|
||||||
T: io::Read,
|
T: AsyncRead + Unpin,
|
||||||
{
|
{
|
||||||
let mut read_some = false;
|
let mut read_some = false;
|
||||||
loop {
|
loop {
|
||||||
@ -810,19 +844,18 @@ where
|
|||||||
buf.reserve(HW_BUFFER_SIZE);
|
buf.reserve(HW_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
let read = unsafe { io.read(buf.bytes_mut()) };
|
match read(cx, io, buf) {
|
||||||
match read {
|
Poll::Pending => {
|
||||||
Ok(n) => {
|
return if read_some { Ok(Some(false)) } else { Ok(None) };
|
||||||
|
}
|
||||||
|
Poll::Ready(Ok(n)) => {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return Ok(Some(true));
|
return Ok(Some(true));
|
||||||
} else {
|
} else {
|
||||||
read_some = true;
|
read_some = true;
|
||||||
unsafe {
|
|
||||||
buf.advance_mut(n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Poll::Ready(Err(e)) => {
|
||||||
return if e.kind() == io::ErrorKind::WouldBlock {
|
return if e.kind() == io::ErrorKind::WouldBlock {
|
||||||
if read_some {
|
if read_some {
|
||||||
Ok(Some(false))
|
Ok(Some(false))
|
||||||
@ -833,12 +866,23 @@ where
|
|||||||
Ok(Some(true))
|
Ok(Some(true))
|
||||||
} else {
|
} else {
|
||||||
Err(e)
|
Err(e)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read<T>(
|
||||||
|
cx: &mut Context,
|
||||||
|
io: &mut T,
|
||||||
|
buf: &mut BytesMut,
|
||||||
|
) -> Poll<Result<usize, io::Error>>
|
||||||
|
where
|
||||||
|
T: AsyncRead + Unpin,
|
||||||
|
{
|
||||||
|
Pin::new(io).poll_read_buf(cx, buf)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use actix_service::IntoService;
|
use actix_service::IntoService;
|
||||||
|
@ -1,21 +1,24 @@
|
|||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_server_config::ServerConfig;
|
use actix_server_config::ServerConfig;
|
||||||
use actix_service::{NewService, Service};
|
use actix_service::{Service, ServiceFactory};
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, Ready};
|
||||||
use futures::{Async, Poll};
|
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::request::Request;
|
use crate::request::Request;
|
||||||
|
|
||||||
pub struct ExpectHandler;
|
pub struct ExpectHandler;
|
||||||
|
|
||||||
impl NewService for ExpectHandler {
|
impl ServiceFactory for ExpectHandler {
|
||||||
type Config = ServerConfig;
|
type Config = ServerConfig;
|
||||||
type Request = Request;
|
type Request = Request;
|
||||||
type Response = Request;
|
type Response = Request;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Service = ExpectHandler;
|
type Service = ExpectHandler;
|
||||||
type InitError = Error;
|
type InitError = Error;
|
||||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
fn new_service(&self, _: &ServerConfig) -> Self::Future {
|
fn new_service(&self, _: &ServerConfig) -> Self::Future {
|
||||||
ok(ExpectHandler)
|
ok(ExpectHandler)
|
||||||
@ -26,10 +29,10 @@ impl Service for ExpectHandler {
|
|||||||
type Request = Request;
|
type Request = Request;
|
||||||
type Response = Request;
|
type Response = Request;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Future = FutureResult<Self::Response, Self::Error>;
|
type Future = Ready<Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future {
|
fn call(&mut self, req: Request) -> Self::Future {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
//! Payload stream
|
//! Payload stream
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
use actix_utils::task::LocalWaker;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::task::current as current_task;
|
use futures::Stream;
|
||||||
use futures::task::Task;
|
|
||||||
use futures::{Async, Poll, Stream};
|
|
||||||
|
|
||||||
use crate::error::PayloadError;
|
use crate::error::PayloadError;
|
||||||
|
|
||||||
@ -77,15 +79,24 @@ impl Payload {
|
|||||||
pub fn unread_data(&mut self, data: Bytes) {
|
pub fn unread_data(&mut self, data: Bytes) {
|
||||||
self.inner.borrow_mut().unread_data(data);
|
self.inner.borrow_mut().unread_data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn readany(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||||
|
self.inner.borrow_mut().readany(cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for Payload {
|
impl Stream for Payload {
|
||||||
type Item = Bytes;
|
type Item = Result<Bytes, PayloadError>;
|
||||||
type Error = PayloadError;
|
|
||||||
|
|
||||||
#[inline]
|
fn poll_next(
|
||||||
fn poll(&mut self) -> Poll<Option<Bytes>, PayloadError> {
|
self: Pin<&mut Self>,
|
||||||
self.inner.borrow_mut().readany()
|
cx: &mut Context,
|
||||||
|
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||||
|
self.inner.borrow_mut().readany(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,19 +128,14 @@ impl PayloadSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn need_read(&self) -> PayloadStatus {
|
pub fn need_read(&self, cx: &mut Context) -> PayloadStatus {
|
||||||
// we check need_read only if Payload (other side) is alive,
|
// we check need_read only if Payload (other side) is alive,
|
||||||
// otherwise always return true (consume payload)
|
// otherwise always return true (consume payload)
|
||||||
if let Some(shared) = self.inner.upgrade() {
|
if let Some(shared) = self.inner.upgrade() {
|
||||||
if shared.borrow().need_read {
|
if shared.borrow().need_read {
|
||||||
PayloadStatus::Read
|
PayloadStatus::Read
|
||||||
} else {
|
} else {
|
||||||
#[cfg(not(test))]
|
shared.borrow_mut().io_task.register(cx.waker());
|
||||||
{
|
|
||||||
if shared.borrow_mut().io_task.is_none() {
|
|
||||||
shared.borrow_mut().io_task = Some(current_task());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PayloadStatus::Pause
|
PayloadStatus::Pause
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -145,8 +151,8 @@ struct Inner {
|
|||||||
err: Option<PayloadError>,
|
err: Option<PayloadError>,
|
||||||
need_read: bool,
|
need_read: bool,
|
||||||
items: VecDeque<Bytes>,
|
items: VecDeque<Bytes>,
|
||||||
task: Option<Task>,
|
task: LocalWaker,
|
||||||
io_task: Option<Task>,
|
io_task: LocalWaker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inner {
|
impl Inner {
|
||||||
@ -157,8 +163,8 @@ impl Inner {
|
|||||||
err: None,
|
err: None,
|
||||||
items: VecDeque::new(),
|
items: VecDeque::new(),
|
||||||
need_read: true,
|
need_read: true,
|
||||||
task: None,
|
task: LocalWaker::new(),
|
||||||
io_task: None,
|
io_task: LocalWaker::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +184,7 @@ impl Inner {
|
|||||||
self.items.push_back(data);
|
self.items.push_back(data);
|
||||||
self.need_read = self.len < MAX_BUFFER_SIZE;
|
self.need_read = self.len < MAX_BUFFER_SIZE;
|
||||||
if let Some(task) = self.task.take() {
|
if let Some(task) = self.task.take() {
|
||||||
task.notify()
|
task.wake()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,34 +193,28 @@ impl Inner {
|
|||||||
self.len
|
self.len
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readany(&mut self) -> Poll<Option<Bytes>, PayloadError> {
|
fn readany(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||||
if let Some(data) = self.items.pop_front() {
|
if let Some(data) = self.items.pop_front() {
|
||||||
self.len -= data.len();
|
self.len -= data.len();
|
||||||
self.need_read = self.len < MAX_BUFFER_SIZE;
|
self.need_read = self.len < MAX_BUFFER_SIZE;
|
||||||
|
|
||||||
if self.need_read && self.task.is_none() && !self.eof {
|
if self.need_read && !self.eof {
|
||||||
self.task = Some(current_task());
|
self.task.register(cx.waker());
|
||||||
}
|
}
|
||||||
if let Some(task) = self.io_task.take() {
|
self.io_task.wake();
|
||||||
task.notify()
|
Poll::Ready(Some(Ok(data)))
|
||||||
}
|
|
||||||
Ok(Async::Ready(Some(data)))
|
|
||||||
} else if let Some(err) = self.err.take() {
|
} else if let Some(err) = self.err.take() {
|
||||||
Err(err)
|
Poll::Ready(Some(Err(err)))
|
||||||
} else if self.eof {
|
} else if self.eof {
|
||||||
Ok(Async::Ready(None))
|
Poll::Ready(None)
|
||||||
} else {
|
} else {
|
||||||
self.need_read = true;
|
self.need_read = true;
|
||||||
#[cfg(not(test))]
|
self.task.register(cx.waker());
|
||||||
{
|
self.io_task.wake();
|
||||||
if self.task.is_none() {
|
Poll::Pending
|
||||||
self.task = Some(current_task());
|
|
||||||
}
|
|
||||||
if let Some(task) = self.io_task.take() {
|
|
||||||
task.notify()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Async::NotReady)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_codec::Framed;
|
use actix_codec::Framed;
|
||||||
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
|
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
use actix_service::{IntoServiceFactory, Service, ServiceFactory};
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, Ready};
|
||||||
use futures::{try_ready, Async, Future, IntoFuture, Poll, Stream};
|
use futures::{ready, Stream};
|
||||||
|
|
||||||
use crate::body::MessageBody;
|
use crate::body::MessageBody;
|
||||||
use crate::cloneable::CloneableService;
|
use crate::cloneable::CloneableService;
|
||||||
@ -20,7 +23,7 @@ use super::codec::Codec;
|
|||||||
use super::dispatcher::Dispatcher;
|
use super::dispatcher::Dispatcher;
|
||||||
use super::{ExpectHandler, Message, UpgradeHandler};
|
use super::{ExpectHandler, Message, UpgradeHandler};
|
||||||
|
|
||||||
/// `NewService` implementation for HTTP1 transport
|
/// `ServiceFactory` implementation for HTTP1 transport
|
||||||
pub struct H1Service<T, P, S, B, X = ExpectHandler, U = UpgradeHandler<T>> {
|
pub struct H1Service<T, P, S, B, X = ExpectHandler, U = UpgradeHandler<T>> {
|
||||||
srv: S,
|
srv: S,
|
||||||
cfg: ServiceConfig,
|
cfg: ServiceConfig,
|
||||||
@ -32,19 +35,23 @@ pub struct H1Service<T, P, S, B, X = ExpectHandler, U = UpgradeHandler<T>> {
|
|||||||
|
|
||||||
impl<T, P, S, B> H1Service<T, P, S, B>
|
impl<T, P, S, B> H1Service<T, P, S, B>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
/// Create new `HttpService` instance with default config.
|
/// Create new `HttpService` instance with default config.
|
||||||
pub fn new<F: IntoNewService<S>>(service: F) -> Self {
|
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self {
|
||||||
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0);
|
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0);
|
||||||
|
|
||||||
H1Service {
|
H1Service {
|
||||||
cfg,
|
cfg,
|
||||||
srv: service.into_new_service(),
|
srv: service.into_factory(),
|
||||||
expect: ExpectHandler,
|
expect: ExpectHandler,
|
||||||
upgrade: None,
|
upgrade: None,
|
||||||
on_connect: None,
|
on_connect: None,
|
||||||
@ -53,10 +60,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create new `HttpService` instance with config.
|
/// Create new `HttpService` instance with config.
|
||||||
pub fn with_config<F: IntoNewService<S>>(cfg: ServiceConfig, service: F) -> Self {
|
pub fn with_config<F: IntoServiceFactory<S>>(
|
||||||
|
cfg: ServiceConfig,
|
||||||
|
service: F,
|
||||||
|
) -> Self {
|
||||||
H1Service {
|
H1Service {
|
||||||
cfg,
|
cfg,
|
||||||
srv: service.into_new_service(),
|
srv: service.into_factory(),
|
||||||
expect: ExpectHandler,
|
expect: ExpectHandler,
|
||||||
upgrade: None,
|
upgrade: None,
|
||||||
on_connect: None,
|
on_connect: None,
|
||||||
@ -67,17 +77,24 @@ where
|
|||||||
|
|
||||||
impl<T, P, S, B, X, U> H1Service<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> H1Service<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
pub fn expect<X1>(self, expect: X1) -> H1Service<T, P, S, B, X1, U>
|
pub fn expect<X1>(self, expect: X1) -> H1Service<T, P, S, B, X1, U>
|
||||||
where
|
where
|
||||||
X1: NewService<Request = Request, Response = Request>,
|
X1: ServiceFactory<Request = Request, Response = Request>,
|
||||||
X1::Error: Into<Error>,
|
X1::Error: Into<Error>,
|
||||||
X1::InitError: fmt::Debug,
|
X1::InitError: fmt::Debug,
|
||||||
|
X1::Future: Unpin,
|
||||||
|
X1::Service: Unpin,
|
||||||
|
<X1::Service as Service>::Future: Unpin,
|
||||||
{
|
{
|
||||||
H1Service {
|
H1Service {
|
||||||
expect,
|
expect,
|
||||||
@ -91,9 +108,12 @@ where
|
|||||||
|
|
||||||
pub fn upgrade<U1>(self, upgrade: Option<U1>) -> H1Service<T, P, S, B, X, U1>
|
pub fn upgrade<U1>(self, upgrade: Option<U1>) -> H1Service<T, P, S, B, X, U1>
|
||||||
where
|
where
|
||||||
U1: NewService<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U1: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||||
U1::Error: fmt::Display,
|
U1::Error: fmt::Display,
|
||||||
U1::InitError: fmt::Debug,
|
U1::InitError: fmt::Debug,
|
||||||
|
U1::Future: Unpin,
|
||||||
|
U1::Service: Unpin,
|
||||||
|
<U1::Service as Service>::Future: Unpin,
|
||||||
{
|
{
|
||||||
H1Service {
|
H1Service {
|
||||||
upgrade,
|
upgrade,
|
||||||
@ -115,24 +135,35 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> NewService for H1Service<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> ServiceFactory for H1Service<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
|
S::Service: Unpin,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: NewService<Config = SrvConfig, Request = Request, Response = Request>,
|
X: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
X::InitError: fmt::Debug,
|
X::InitError: fmt::Debug,
|
||||||
U: NewService<
|
X::Future: Unpin,
|
||||||
|
X::Service: Unpin,
|
||||||
|
<X::Service as Service>::Future: Unpin,
|
||||||
|
U: ServiceFactory<
|
||||||
Config = SrvConfig,
|
Config = SrvConfig,
|
||||||
Request = (Request, Framed<T, Codec>),
|
Request = (Request, Framed<T, Codec>),
|
||||||
Response = (),
|
Response = (),
|
||||||
>,
|
>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
U::InitError: fmt::Debug,
|
U::InitError: fmt::Debug,
|
||||||
|
U::Future: Unpin,
|
||||||
|
U::Service: Unpin,
|
||||||
|
<U::Service as Service>::Future: Unpin,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Config = SrvConfig;
|
type Config = SrvConfig;
|
||||||
type Request = Io<T, P>;
|
type Request = Io<T, P>;
|
||||||
@ -144,7 +175,7 @@ where
|
|||||||
|
|
||||||
fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
|
fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
|
||||||
H1ServiceResponse {
|
H1ServiceResponse {
|
||||||
fut: self.srv.new_service(cfg).into_future(),
|
fut: self.srv.new_service(cfg),
|
||||||
fut_ex: Some(self.expect.new_service(cfg)),
|
fut_ex: Some(self.expect.new_service(cfg)),
|
||||||
fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)),
|
fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)),
|
||||||
expect: None,
|
expect: None,
|
||||||
@ -159,15 +190,25 @@ where
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct H1ServiceResponse<T, P, S, B, X, U>
|
pub struct H1ServiceResponse<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
S: NewService<Request = Request>,
|
S: ServiceFactory<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
X: NewService<Request = Request, Response = Request>,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin,
|
||||||
|
X: ServiceFactory<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
X::InitError: fmt::Debug,
|
X::InitError: fmt::Debug,
|
||||||
U: NewService<Request = (Request, Framed<T, Codec>), Response = ()>,
|
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::Error: fmt::Display,
|
||||||
U::InitError: fmt::Debug,
|
U::InitError: fmt::Debug,
|
||||||
|
U::Future: Unpin,
|
||||||
|
U::Service: Unpin,
|
||||||
|
<U::Service as Service>::Future: Unpin,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
fut: S::Future,
|
fut: S::Future,
|
||||||
fut_ex: Option<X::Future>,
|
fut_ex: Option<X::Future>,
|
||||||
@ -182,49 +223,63 @@ where
|
|||||||
impl<T, P, S, B, X, U> Future for H1ServiceResponse<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Future for H1ServiceResponse<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: NewService<Request = Request>,
|
S: ServiceFactory<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: NewService<Request = Request, Response = Request>,
|
X: ServiceFactory<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
X::InitError: fmt::Debug,
|
X::InitError: fmt::Debug,
|
||||||
U: NewService<Request = (Request, Framed<T, Codec>), Response = ()>,
|
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::Error: fmt::Display,
|
||||||
U::InitError: fmt::Debug,
|
U::InitError: fmt::Debug,
|
||||||
|
U::Future: Unpin,
|
||||||
|
U::Service: Unpin,
|
||||||
|
<U::Service as Service>::Future: Unpin,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Item = H1ServiceHandler<T, P, S::Service, B, X::Service, U::Service>;
|
type Output =
|
||||||
type Error = ();
|
Result<H1ServiceHandler<T, P, S::Service, B, X::Service, U::Service>, ()>;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
if let Some(ref mut fut) = self.fut_ex {
|
let this = self.get_mut();
|
||||||
let expect = try_ready!(fut
|
|
||||||
.poll()
|
if let Some(ref mut fut) = this.fut_ex {
|
||||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
let expect = ready!(Pin::new(fut)
|
||||||
self.expect = Some(expect);
|
.poll(cx)
|
||||||
self.fut_ex.take();
|
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||||
|
this.expect = Some(expect);
|
||||||
|
this.fut_ex.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut fut) = self.fut_upg {
|
if let Some(ref mut fut) = this.fut_upg {
|
||||||
let upgrade = try_ready!(fut
|
let upgrade = ready!(Pin::new(fut)
|
||||||
.poll()
|
.poll(cx)
|
||||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||||
self.upgrade = Some(upgrade);
|
this.upgrade = Some(upgrade);
|
||||||
self.fut_ex.take();
|
this.fut_ex.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
let service = try_ready!(self
|
let result = ready!(Pin::new(&mut this.fut)
|
||||||
.fut
|
.poll(cx)
|
||||||
.poll()
|
|
||||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
||||||
Ok(Async::Ready(H1ServiceHandler::new(
|
|
||||||
self.cfg.take().unwrap(),
|
Poll::Ready(result.map(|service| {
|
||||||
service,
|
H1ServiceHandler::new(
|
||||||
self.expect.take().unwrap(),
|
this.cfg.take().unwrap(),
|
||||||
self.upgrade.take(),
|
service,
|
||||||
self.on_connect.clone(),
|
this.expect.take().unwrap(),
|
||||||
)))
|
this.upgrade.take(),
|
||||||
|
this.on_connect.clone(),
|
||||||
|
)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,14 +295,18 @@ pub struct H1ServiceHandler<T, P, S, B, X, U> {
|
|||||||
|
|
||||||
impl<T, P, S, B, X, U> H1ServiceHandler<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> H1ServiceHandler<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request> + Unpin,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request> + Unpin,
|
||||||
|
X::Future: Unpin,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()> + Unpin,
|
||||||
|
U::Future: Unpin,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
fn new(
|
fn new(
|
||||||
cfg: ServiceConfig,
|
cfg: ServiceConfig,
|
||||||
@ -270,24 +329,28 @@ where
|
|||||||
impl<T, P, S, B, X, U> Service for H1ServiceHandler<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Service for H1ServiceHandler<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request> + Unpin,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request> + Unpin,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
X::Future: Unpin,
|
||||||
|
U: Service<Request = (Request, Framed<T, Codec>), Response = ()> + Unpin,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Request = Io<T, P>;
|
type Request = Io<T, P>;
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = DispatchError;
|
type Error = DispatchError;
|
||||||
type Future = Dispatcher<T, S, B, X, U>;
|
type Future = Dispatcher<T, S, B, X, U>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
let ready = self
|
let ready = self
|
||||||
.expect
|
.expect
|
||||||
.poll_ready()
|
.poll_ready(cx)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
let e = e.into();
|
let e = e.into();
|
||||||
log::error!("Http service readiness error: {:?}", e);
|
log::error!("Http service readiness error: {:?}", e);
|
||||||
@ -297,7 +360,7 @@ where
|
|||||||
|
|
||||||
let ready = self
|
let ready = self
|
||||||
.srv
|
.srv
|
||||||
.poll_ready()
|
.poll_ready(cx)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
let e = e.into();
|
let e = e.into();
|
||||||
log::error!("Http service readiness error: {:?}", e);
|
log::error!("Http service readiness error: {:?}", e);
|
||||||
@ -307,9 +370,9 @@ where
|
|||||||
&& ready;
|
&& ready;
|
||||||
|
|
||||||
if ready {
|
if ready {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(Ok(()))
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::NotReady)
|
Poll::Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +396,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `NewService` implementation for `OneRequestService` service
|
/// `ServiceFactory` implementation for `OneRequestService` service
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct OneRequest<T, P> {
|
pub struct OneRequest<T, P> {
|
||||||
config: ServiceConfig,
|
config: ServiceConfig,
|
||||||
@ -353,7 +416,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, P> NewService for OneRequest<T, P>
|
impl<T, P> ServiceFactory for OneRequest<T, P>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
{
|
{
|
||||||
@ -363,7 +426,7 @@ where
|
|||||||
type Error = ParseError;
|
type Error = ParseError;
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
type Service = OneRequestService<T, P>;
|
type Service = OneRequestService<T, P>;
|
||||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
fn new_service(&self, _: &SrvConfig) -> Self::Future {
|
fn new_service(&self, _: &SrvConfig) -> Self::Future {
|
||||||
ok(OneRequestService {
|
ok(OneRequestService {
|
||||||
@ -389,8 +452,8 @@ where
|
|||||||
type Error = ParseError;
|
type Error = ParseError;
|
||||||
type Future = OneRequestServiceResponse<T>;
|
type Future = OneRequestServiceResponse<T>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||||
@ -415,19 +478,19 @@ impl<T> Future for OneRequestServiceResponse<T>
|
|||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
{
|
{
|
||||||
type Item = (Request, Framed<T, Codec>);
|
type Output = Result<(Request, Framed<T, Codec>), ParseError>;
|
||||||
type Error = ParseError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
match self.framed.as_mut().unwrap().poll()? {
|
match self.framed.as_mut().unwrap().next_item(cx) {
|
||||||
Async::Ready(Some(req)) => match req {
|
Poll::Ready(Some(Ok(req))) => match req {
|
||||||
Message::Item(req) => {
|
Message::Item(req) => {
|
||||||
Ok(Async::Ready((req, self.framed.take().unwrap())))
|
Poll::Ready(Ok((req, self.framed.take().unwrap())))
|
||||||
}
|
}
|
||||||
Message::Chunk(_) => unreachable!("Something is wrong"),
|
Message::Chunk(_) => unreachable!("Something is wrong"),
|
||||||
},
|
},
|
||||||
Async::Ready(None) => Err(ParseError::Incomplete),
|
Poll::Ready(Some(Err(err))) => Poll::Ready(Err(err)),
|
||||||
Async::NotReady => Ok(Async::NotReady),
|
Poll::Ready(None) => Poll::Ready(Err(ParseError::Incomplete)),
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_codec::Framed;
|
use actix_codec::Framed;
|
||||||
use actix_server_config::ServerConfig;
|
use actix_server_config::ServerConfig;
|
||||||
use actix_service::{NewService, Service};
|
use actix_service::{Service, ServiceFactory};
|
||||||
use futures::future::FutureResult;
|
use futures::future::Ready;
|
||||||
use futures::{Async, Poll};
|
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::h1::Codec;
|
use crate::h1::Codec;
|
||||||
@ -12,14 +14,14 @@ use crate::request::Request;
|
|||||||
|
|
||||||
pub struct UpgradeHandler<T>(PhantomData<T>);
|
pub struct UpgradeHandler<T>(PhantomData<T>);
|
||||||
|
|
||||||
impl<T> NewService for UpgradeHandler<T> {
|
impl<T> ServiceFactory for UpgradeHandler<T> {
|
||||||
type Config = ServerConfig;
|
type Config = ServerConfig;
|
||||||
type Request = (Request, Framed<T, Codec>);
|
type Request = (Request, Framed<T, Codec>);
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Service = UpgradeHandler<T>;
|
type Service = UpgradeHandler<T>;
|
||||||
type InitError = Error;
|
type InitError = Error;
|
||||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
fn new_service(&self, _: &ServerConfig) -> Self::Future {
|
fn new_service(&self, _: &ServerConfig) -> Self::Future {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
@ -30,10 +32,10 @@ impl<T> Service for UpgradeHandler<T> {
|
|||||||
type Request = (Request, Framed<T, Codec>);
|
type Request = (Request, Framed<T, Codec>);
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Future = FutureResult<Self::Response, Self::Error>;
|
type Future = Ready<Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, _: Self::Request) -> Self::Future {
|
fn call(&mut self, _: Self::Request) -> Self::Future {
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
use futures::{Async, Future, Poll, Sink};
|
use futures::Sink;
|
||||||
|
|
||||||
use crate::body::{BodySize, MessageBody, ResponseBody};
|
use crate::body::{BodySize, MessageBody, ResponseBody};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
@ -30,63 +34,64 @@ where
|
|||||||
|
|
||||||
impl<T, B> Future for SendResponse<T, B>
|
impl<T, B> Future for SendResponse<T, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: AsyncRead + AsyncWrite + Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
{
|
{
|
||||||
type Item = Framed<T, Codec>;
|
type Output = Result<Framed<T, Codec>, Error>;
|
||||||
type Error = Error;
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
|
let this = self.get_mut();
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
loop {
|
loop {
|
||||||
let mut body_ready = self.body.is_some();
|
let mut body_ready = this.body.is_some();
|
||||||
let framed = self.framed.as_mut().unwrap();
|
let framed = this.framed.as_mut().unwrap();
|
||||||
|
|
||||||
// send body
|
// send body
|
||||||
if self.res.is_none() && self.body.is_some() {
|
if this.res.is_none() && this.body.is_some() {
|
||||||
while body_ready && self.body.is_some() && !framed.is_write_buf_full() {
|
while body_ready && this.body.is_some() && !framed.is_write_buf_full() {
|
||||||
match self.body.as_mut().unwrap().poll_next()? {
|
match this.body.as_mut().unwrap().poll_next(cx)? {
|
||||||
Async::Ready(item) => {
|
Poll::Ready(item) => {
|
||||||
// body is done
|
// body is done
|
||||||
if item.is_none() {
|
if item.is_none() {
|
||||||
let _ = self.body.take();
|
let _ = this.body.take();
|
||||||
}
|
}
|
||||||
framed.force_send(Message::Chunk(item))?;
|
framed.force_send(Message::Chunk(item))?;
|
||||||
}
|
}
|
||||||
Async::NotReady => body_ready = false,
|
Poll::Pending => body_ready = false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush write buffer
|
// flush write buffer
|
||||||
if !framed.is_write_buf_empty() {
|
if !framed.is_write_buf_empty() {
|
||||||
match framed.poll_complete()? {
|
match framed.flush(cx)? {
|
||||||
Async::Ready(_) => {
|
Poll::Ready(_) => {
|
||||||
if body_ready {
|
if body_ready {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return Ok(Async::NotReady);
|
return Poll::Pending;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Async::NotReady => return Ok(Async::NotReady),
|
Poll::Pending => return Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send response
|
// send response
|
||||||
if let Some(res) = self.res.take() {
|
if let Some(res) = this.res.take() {
|
||||||
framed.force_send(res)?;
|
framed.force_send(res)?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.body.is_some() {
|
if this.body.is_some() {
|
||||||
if body_ready {
|
if body_ready {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return Ok(Async::NotReady);
|
return Poll::Pending;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(self.framed.take().unwrap()))
|
Poll::Ready(Ok(this.framed.take().unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::{fmt, mem, net};
|
use std::{fmt, mem, net};
|
||||||
|
|
||||||
@ -8,7 +11,7 @@ use actix_server_config::IoStream;
|
|||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures::{try_ready, Async, Future, Poll, Sink, Stream};
|
use futures::{ready, Sink, Stream};
|
||||||
use h2::server::{Connection, SendResponse};
|
use h2::server::{Connection, SendResponse};
|
||||||
use h2::{RecvStream, SendStream};
|
use h2::{RecvStream, SendStream};
|
||||||
use http::header::{
|
use http::header::{
|
||||||
@ -43,13 +46,24 @@ pub struct Dispatcher<T: IoStream, S: Service<Request = Request>, B: MessageBody
|
|||||||
_t: PhantomData<B>,
|
_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>
|
impl<T, S, B> Dispatcher<T, S, B>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
@ -93,61 +107,75 @@ impl<T, S, B> Future for Dispatcher<T, S, B>
|
|||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
{
|
{
|
||||||
type Item = ();
|
type Output = Result<(), DispatchError>;
|
||||||
type Error = DispatchError;
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
|
let this = self.get_mut();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.connection.poll()? {
|
match Pin::new(&mut this.connection).poll_accept(cx) {
|
||||||
Async::Ready(None) => return Ok(Async::Ready(())),
|
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
||||||
Async::Ready(Some((req, res))) => {
|
Poll::Ready(Some(Err(err))) => return Poll::Ready(Err(err.into())),
|
||||||
|
Poll::Ready(Some(Ok((req, res)))) => {
|
||||||
// update keep-alive expire
|
// update keep-alive expire
|
||||||
if self.ka_timer.is_some() {
|
if this.ka_timer.is_some() {
|
||||||
if let Some(expire) = self.config.keep_alive_expire() {
|
if let Some(expire) = this.config.keep_alive_expire() {
|
||||||
self.ka_expire = expire;
|
this.ka_expire = expire;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (parts, body) = req.into_parts();
|
let (parts, body) = req.into_parts();
|
||||||
let mut req = Request::with_payload(body.into());
|
// let b: () = body;
|
||||||
|
let mut req = Request::with_payload(Payload::<
|
||||||
|
crate::payload::PayloadStream,
|
||||||
|
>::H2(
|
||||||
|
crate::h2::Payload::new(body)
|
||||||
|
));
|
||||||
|
|
||||||
let head = &mut req.head_mut();
|
let head = &mut req.head_mut();
|
||||||
head.uri = parts.uri;
|
head.uri = parts.uri;
|
||||||
head.method = parts.method;
|
head.method = parts.method;
|
||||||
head.version = parts.version;
|
head.version = parts.version;
|
||||||
head.headers = parts.headers.into();
|
head.headers = parts.headers.into();
|
||||||
head.peer_addr = self.peer_addr;
|
head.peer_addr = this.peer_addr;
|
||||||
|
|
||||||
// set on_connect data
|
// set on_connect data
|
||||||
if let Some(ref on_connect) = self.on_connect {
|
if let Some(ref on_connect) = this.on_connect {
|
||||||
on_connect.set(&mut req.extensions_mut());
|
on_connect.set(&mut req.extensions_mut());
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio_current_thread::spawn(ServiceResponse::<S::Future, B> {
|
// tokio_executor::current_thread::spawn(ServiceResponse::<
|
||||||
state: ServiceResponseState::ServiceCall(
|
// S::Future,
|
||||||
self.service.call(req),
|
// S::Response,
|
||||||
Some(res),
|
// S::Error,
|
||||||
),
|
// B,
|
||||||
config: self.config.clone(),
|
// > {
|
||||||
buffer: None,
|
// state: ServiceResponseState::ServiceCall(
|
||||||
})
|
// this.service.call(req),
|
||||||
|
// Some(res),
|
||||||
|
// ),
|
||||||
|
// config: this.config.clone(),
|
||||||
|
// buffer: None,
|
||||||
|
// _t: PhantomData,
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
Async::NotReady => return Ok(Async::NotReady),
|
Poll::Pending => return Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServiceResponse<F, B> {
|
struct ServiceResponse<F, I, E, B> {
|
||||||
state: ServiceResponseState<F, B>,
|
state: ServiceResponseState<F, B>,
|
||||||
config: ServiceConfig,
|
config: ServiceConfig,
|
||||||
buffer: Option<Bytes>,
|
buffer: Option<Bytes>,
|
||||||
|
_t: PhantomData<(I, E)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ServiceResponseState<F, B> {
|
enum ServiceResponseState<F, B> {
|
||||||
@ -155,11 +183,11 @@ enum ServiceResponseState<F, B> {
|
|||||||
SendPayload(SendStream<Bytes>, ResponseBody<B>),
|
SendPayload(SendStream<Bytes>, ResponseBody<B>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, B> ServiceResponse<F, B>
|
impl<F, I, E, B> ServiceResponse<F, I, E, B>
|
||||||
where
|
where
|
||||||
F: Future,
|
F: Future<Output = Result<I, E>> + Unpin,
|
||||||
F::Error: Into<Error>,
|
E: Into<Error> + Unpin + 'static,
|
||||||
F::Item: Into<Response<B>>,
|
I: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
{
|
{
|
||||||
fn prepare_response(
|
fn prepare_response(
|
||||||
@ -223,109 +251,116 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, B> Future for ServiceResponse<F, B>
|
impl<F, I, E, B> Future for ServiceResponse<F, I, E, B>
|
||||||
where
|
where
|
||||||
F: Future,
|
F: Future<Output = Result<I, E>> + Unpin,
|
||||||
F::Error: Into<Error>,
|
E: Into<Error> + Unpin + 'static,
|
||||||
F::Item: Into<Response<B>>,
|
I: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
{
|
{
|
||||||
type Item = ();
|
type Output = ();
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
match self.state {
|
let this = self.get_mut();
|
||||||
|
|
||||||
|
match this.state {
|
||||||
ServiceResponseState::ServiceCall(ref mut call, ref mut send) => {
|
ServiceResponseState::ServiceCall(ref mut call, ref mut send) => {
|
||||||
match call.poll() {
|
match Pin::new(call).poll(cx) {
|
||||||
Ok(Async::Ready(res)) => {
|
Poll::Ready(Ok(res)) => {
|
||||||
let (res, body) = res.into().replace_body(());
|
let (res, body) = res.into().replace_body(());
|
||||||
|
|
||||||
let mut send = send.take().unwrap();
|
let mut send = send.take().unwrap();
|
||||||
let mut size = body.size();
|
let mut size = body.size();
|
||||||
let h2_res = self.prepare_response(res.head(), &mut size);
|
let h2_res = this.prepare_response(res.head(), &mut size);
|
||||||
|
|
||||||
let stream =
|
let stream = match send.send_response(h2_res, size.is_eof()) {
|
||||||
send.send_response(h2_res, size.is_eof()).map_err(|e| {
|
Err(e) => {
|
||||||
trace!("Error sending h2 response: {:?}", e);
|
trace!("Error sending h2 response: {:?}", e);
|
||||||
})?;
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
Ok(stream) => stream,
|
||||||
|
};
|
||||||
|
|
||||||
if size.is_eof() {
|
if size.is_eof() {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(())
|
||||||
} else {
|
} else {
|
||||||
self.state = ServiceResponseState::SendPayload(stream, body);
|
this.state = ServiceResponseState::SendPayload(stream, body);
|
||||||
self.poll()
|
Pin::new(this).poll(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
Poll::Pending => Poll::Pending,
|
||||||
Err(e) => {
|
Poll::Ready(Err(e)) => {
|
||||||
let res: Response = e.into().into();
|
let res: Response = e.into().into();
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
|
|
||||||
let mut send = send.take().unwrap();
|
let mut send = send.take().unwrap();
|
||||||
let mut size = body.size();
|
let mut size = body.size();
|
||||||
let h2_res = self.prepare_response(res.head(), &mut size);
|
let h2_res = this.prepare_response(res.head(), &mut size);
|
||||||
|
|
||||||
let stream =
|
let stream = match send.send_response(h2_res, size.is_eof()) {
|
||||||
send.send_response(h2_res, size.is_eof()).map_err(|e| {
|
Err(e) => {
|
||||||
trace!("Error sending h2 response: {:?}", e);
|
trace!("Error sending h2 response: {:?}", e);
|
||||||
})?;
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
Ok(stream) => stream,
|
||||||
|
};
|
||||||
|
|
||||||
if size.is_eof() {
|
if size.is_eof() {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(())
|
||||||
} else {
|
} else {
|
||||||
self.state = ServiceResponseState::SendPayload(
|
this.state = ServiceResponseState::SendPayload(
|
||||||
stream,
|
stream,
|
||||||
body.into_body(),
|
body.into_body(),
|
||||||
);
|
);
|
||||||
self.poll()
|
Pin::new(this).poll(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ServiceResponseState::SendPayload(ref mut stream, ref mut body) => loop {
|
ServiceResponseState::SendPayload(ref mut stream, ref mut body) => loop {
|
||||||
loop {
|
loop {
|
||||||
if let Some(ref mut buffer) = self.buffer {
|
if let Some(ref mut buffer) = this.buffer {
|
||||||
match stream.poll_capacity().map_err(|e| warn!("{:?}", e))? {
|
match stream.poll_capacity(cx) {
|
||||||
Async::NotReady => return Ok(Async::NotReady),
|
Poll::Pending => return Poll::Pending,
|
||||||
Async::Ready(None) => return Ok(Async::Ready(())),
|
Poll::Ready(None) => return Poll::Ready(()),
|
||||||
Async::Ready(Some(cap)) => {
|
Poll::Ready(Some(Ok(cap))) => {
|
||||||
let len = buffer.len();
|
let len = buffer.len();
|
||||||
let bytes = buffer.split_to(std::cmp::min(cap, len));
|
let bytes = buffer.split_to(std::cmp::min(cap, len));
|
||||||
|
|
||||||
if let Err(e) = stream.send_data(bytes, false) {
|
if let Err(e) = stream.send_data(bytes, false) {
|
||||||
warn!("{:?}", e);
|
warn!("{:?}", e);
|
||||||
return Err(());
|
return Poll::Ready(());
|
||||||
} else if !buffer.is_empty() {
|
} else if !buffer.is_empty() {
|
||||||
let cap = std::cmp::min(buffer.len(), CHUNK_SIZE);
|
let cap = std::cmp::min(buffer.len(), CHUNK_SIZE);
|
||||||
stream.reserve_capacity(cap);
|
stream.reserve_capacity(cap);
|
||||||
} else {
|
} else {
|
||||||
self.buffer.take();
|
this.buffer.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Poll::Ready(Some(Err(e))) => {
|
||||||
|
warn!("{:?}", e);
|
||||||
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match body.poll_next() {
|
match body.poll_next(cx) {
|
||||||
Ok(Async::NotReady) => {
|
Poll::Pending => return Poll::Pending,
|
||||||
return Ok(Async::NotReady);
|
Poll::Ready(None) => {
|
||||||
}
|
|
||||||
Ok(Async::Ready(None)) => {
|
|
||||||
if let Err(e) = stream.send_data(Bytes::new(), true) {
|
if let Err(e) = stream.send_data(Bytes::new(), true) {
|
||||||
warn!("{:?}", e);
|
warn!("{:?}", e);
|
||||||
return Err(());
|
|
||||||
} else {
|
|
||||||
return Ok(Async::Ready(()));
|
|
||||||
}
|
}
|
||||||
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(Some(chunk))) => {
|
Poll::Ready(Some(Ok(chunk))) => {
|
||||||
stream.reserve_capacity(std::cmp::min(
|
stream.reserve_capacity(std::cmp::min(
|
||||||
chunk.len(),
|
chunk.len(),
|
||||||
CHUNK_SIZE,
|
CHUNK_SIZE,
|
||||||
));
|
));
|
||||||
self.buffer = Some(chunk);
|
this.buffer = Some(chunk);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Poll::Ready(Some(Err(e))) => {
|
||||||
error!("Response payload stream error: {:?}", e);
|
error!("Response payload stream error: {:?}", e);
|
||||||
return Err(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#![allow(dead_code, unused_imports)]
|
#![allow(dead_code, unused_imports)]
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::{Async, Poll, Stream};
|
use futures::Stream;
|
||||||
use h2::RecvStream;
|
use h2::RecvStream;
|
||||||
|
|
||||||
mod dispatcher;
|
mod dispatcher;
|
||||||
@ -25,22 +27,23 @@ impl Payload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for Payload {
|
impl Stream for Payload {
|
||||||
type Item = Bytes;
|
type Item = Result<Bytes, PayloadError>;
|
||||||
type Error = PayloadError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||||
match self.pl.poll() {
|
let this = self.get_mut();
|
||||||
Ok(Async::Ready(Some(chunk))) => {
|
|
||||||
|
match Pin::new(&mut this.pl).poll_data(cx) {
|
||||||
|
Poll::Ready(Some(Ok(chunk))) => {
|
||||||
let len = chunk.len();
|
let len = chunk.len();
|
||||||
if let Err(err) = self.pl.release_capacity().release_capacity(len) {
|
if let Err(err) = this.pl.release_capacity().release_capacity(len) {
|
||||||
Err(err.into())
|
Poll::Ready(Some(Err(err.into())))
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(Some(chunk)))
|
Poll::Ready(Some(Ok(chunk)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
|
Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(err.into()))),
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
Poll::Pending => Poll::Pending,
|
||||||
Err(err) => Err(err.into()),
|
Poll::Ready(None) => Poll::Ready(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::{io, net, rc};
|
use std::{io, net, rc};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
|
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
use actix_service::{IntoServiceFactory, Service, ServiceFactory};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, Ready};
|
||||||
use futures::{try_ready, Async, Future, IntoFuture, Poll, Stream};
|
use futures::{ready, Stream};
|
||||||
use h2::server::{self, Connection, Handshake};
|
use h2::server::{self, Connection, Handshake};
|
||||||
use h2::RecvStream;
|
use h2::RecvStream;
|
||||||
use log::error;
|
use log::error;
|
||||||
@ -23,7 +26,7 @@ use crate::response::Response;
|
|||||||
|
|
||||||
use super::dispatcher::Dispatcher;
|
use super::dispatcher::Dispatcher;
|
||||||
|
|
||||||
/// `NewService` implementation for HTTP2 transport
|
/// `ServiceFactory` implementation for HTTP2 transport
|
||||||
pub struct H2Service<T, P, S, B> {
|
pub struct H2Service<T, P, S, B> {
|
||||||
srv: S,
|
srv: S,
|
||||||
cfg: ServiceConfig,
|
cfg: ServiceConfig,
|
||||||
@ -33,30 +36,35 @@ pub struct H2Service<T, P, S, B> {
|
|||||||
|
|
||||||
impl<T, P, S, B> H2Service<T, P, S, B>
|
impl<T, P, S, B> H2Service<T, P, S, B>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
/// Create new `HttpService` instance.
|
/// Create new `HttpService` instance.
|
||||||
pub fn new<F: IntoNewService<S>>(service: F) -> Self {
|
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self {
|
||||||
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0);
|
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0);
|
||||||
|
|
||||||
H2Service {
|
H2Service {
|
||||||
cfg,
|
cfg,
|
||||||
on_connect: None,
|
on_connect: None,
|
||||||
srv: service.into_new_service(),
|
srv: service.into_factory(),
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new `HttpService` instance with config.
|
/// Create new `HttpService` instance with config.
|
||||||
pub fn with_config<F: IntoNewService<S>>(cfg: ServiceConfig, service: F) -> Self {
|
pub fn with_config<F: IntoServiceFactory<S>>(
|
||||||
|
cfg: ServiceConfig,
|
||||||
|
service: F,
|
||||||
|
) -> Self {
|
||||||
H2Service {
|
H2Service {
|
||||||
cfg,
|
cfg,
|
||||||
on_connect: None,
|
on_connect: None,
|
||||||
srv: service.into_new_service(),
|
srv: service.into_factory(),
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,14 +79,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, P, S, B> NewService for H2Service<T, P, S, B>
|
impl<T, P, S, B> ServiceFactory for H2Service<T, P, S, B>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Config = SrvConfig;
|
type Config = SrvConfig;
|
||||||
type Request = Io<T, P>;
|
type Request = Io<T, P>;
|
||||||
@ -90,7 +100,7 @@ where
|
|||||||
|
|
||||||
fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
|
fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
|
||||||
H2ServiceResponse {
|
H2ServiceResponse {
|
||||||
fut: self.srv.new_service(cfg).into_future(),
|
fut: self.srv.new_service(cfg),
|
||||||
cfg: Some(self.cfg.clone()),
|
cfg: Some(self.cfg.clone()),
|
||||||
on_connect: self.on_connect.clone(),
|
on_connect: self.on_connect.clone(),
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
@ -99,8 +109,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct H2ServiceResponse<T, P, S: NewService, B> {
|
pub struct H2ServiceResponse<T, P, S: ServiceFactory, B> {
|
||||||
fut: <S::Future as IntoFuture>::Future,
|
fut: S::Future,
|
||||||
cfg: Option<ServiceConfig>,
|
cfg: Option<ServiceConfig>,
|
||||||
on_connect: Option<rc::Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
|
on_connect: Option<rc::Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
|
||||||
_t: PhantomData<(T, P, B)>,
|
_t: PhantomData<(T, P, B)>,
|
||||||
@ -109,22 +119,26 @@ pub struct H2ServiceResponse<T, P, S: NewService, B> {
|
|||||||
impl<T, P, S, B> Future for H2ServiceResponse<T, P, S, B>
|
impl<T, P, S, B> Future for H2ServiceResponse<T, P, S, B>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Item = H2ServiceHandler<T, P, S::Service, B>;
|
type Output = Result<H2ServiceHandler<T, P, S::Service, B>, S::InitError>;
|
||||||
type Error = S::InitError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
let service = try_ready!(self.fut.poll());
|
let this = self.get_mut();
|
||||||
Ok(Async::Ready(H2ServiceHandler::new(
|
|
||||||
self.cfg.take().unwrap(),
|
Poll::Ready(ready!(Pin::new(&mut this.fut).poll(cx)).map(|service| {
|
||||||
self.on_connect.clone(),
|
H2ServiceHandler::new(
|
||||||
service,
|
this.cfg.take().unwrap(),
|
||||||
)))
|
this.on_connect.clone(),
|
||||||
|
service,
|
||||||
|
)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,10 +153,11 @@ pub struct H2ServiceHandler<T, P, S, B> {
|
|||||||
impl<T, P, S, B> H2ServiceHandler<T, P, S, B>
|
impl<T, P, S, B> H2ServiceHandler<T, P, S, B>
|
||||||
where
|
where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
fn new(
|
fn new(
|
||||||
cfg: ServiceConfig,
|
cfg: ServiceConfig,
|
||||||
@ -162,18 +177,19 @@ impl<T, P, S, B> Service for H2ServiceHandler<T, P, S, B>
|
|||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Request = Io<T, P>;
|
type Request = Io<T, P>;
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = DispatchError;
|
type Error = DispatchError;
|
||||||
type Future = H2ServiceHandlerResponse<T, S, B>;
|
type Future = H2ServiceHandlerResponse<T, S, B>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
self.srv.poll_ready().map_err(|e| {
|
self.srv.poll_ready(cx).map_err(|e| {
|
||||||
let e = e.into();
|
let e = e.into();
|
||||||
error!("Service readiness error: {:?}", e);
|
error!("Service readiness error: {:?}", e);
|
||||||
DispatchError::Service(e)
|
DispatchError::Service(e)
|
||||||
@ -219,9 +235,9 @@ pub struct H2ServiceHandlerResponse<T, S, B>
|
|||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
{
|
{
|
||||||
state: State<T, S, B>,
|
state: State<T, S, B>,
|
||||||
@ -231,25 +247,24 @@ impl<T, S, B> Future for H2ServiceHandlerResponse<T, S, B>
|
|||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
{
|
{
|
||||||
type Item = ();
|
type Output = Result<(), DispatchError>;
|
||||||
type Error = DispatchError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Incoming(ref mut disp) => disp.poll(),
|
State::Incoming(ref mut disp) => Pin::new(disp).poll(cx),
|
||||||
State::Handshake(
|
State::Handshake(
|
||||||
ref mut srv,
|
ref mut srv,
|
||||||
ref mut config,
|
ref mut config,
|
||||||
ref peer_addr,
|
ref peer_addr,
|
||||||
ref mut on_connect,
|
ref mut on_connect,
|
||||||
ref mut handshake,
|
ref mut handshake,
|
||||||
) => match handshake.poll() {
|
) => match Pin::new(handshake).poll(cx) {
|
||||||
Ok(Async::Ready(conn)) => {
|
Poll::Ready(Ok(conn)) => {
|
||||||
self.state = State::Incoming(Dispatcher::new(
|
self.state = State::Incoming(Dispatcher::new(
|
||||||
srv.take().unwrap(),
|
srv.take().unwrap(),
|
||||||
conn,
|
conn,
|
||||||
@ -258,13 +273,13 @@ where
|
|||||||
None,
|
None,
|
||||||
*peer_addr,
|
*peer_addr,
|
||||||
));
|
));
|
||||||
self.poll()
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
Poll::Ready(Err(err)) => {
|
||||||
Err(err) => {
|
|
||||||
trace!("H2 handshake error: {}", err);
|
trace!("H2 handshake error: {}", err);
|
||||||
Err(err.into())
|
Poll::Ready(Err(err.into()))
|
||||||
}
|
}
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
clippy::too_many_arguments,
|
clippy::too_many_arguments,
|
||||||
clippy::new_without_default,
|
clippy::new_without_default,
|
||||||
clippy::borrow_interior_mutable_const,
|
clippy::borrow_interior_mutable_const,
|
||||||
clippy::write_with_newline
|
clippy::write_with_newline,
|
||||||
|
unused_imports
|
||||||
)]
|
)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -12,7 +13,7 @@ extern crate log;
|
|||||||
|
|
||||||
pub mod body;
|
pub mod body;
|
||||||
mod builder;
|
mod builder;
|
||||||
pub mod client;
|
// pub mod client;
|
||||||
mod cloneable;
|
mod cloneable;
|
||||||
mod config;
|
mod config;
|
||||||
pub mod encoding;
|
pub mod encoding;
|
||||||
@ -31,8 +32,8 @@ pub mod cookie;
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod h1;
|
pub mod h1;
|
||||||
pub mod h2;
|
pub mod h2;
|
||||||
pub mod test;
|
// pub mod test;
|
||||||
pub mod ws;
|
// pub mod ws;
|
||||||
|
|
||||||
pub use self::builder::HttpServiceBuilder;
|
pub use self::builder::HttpServiceBuilder;
|
||||||
pub use self::config::{KeepAlive, ServiceConfig};
|
pub use self::config::{KeepAlive, ServiceConfig};
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::{Async, Poll, Stream};
|
use futures::Stream;
|
||||||
use h2::RecvStream;
|
use h2::RecvStream;
|
||||||
|
|
||||||
use crate::error::PayloadError;
|
use crate::error::PayloadError;
|
||||||
|
|
||||||
/// Type represent boxed payload
|
/// Type represent boxed payload
|
||||||
pub type PayloadStream = Box<dyn Stream<Item = Bytes, Error = PayloadError>>;
|
pub type PayloadStream = Pin<Box<dyn Stream<Item = Result<Bytes, PayloadError>>>>;
|
||||||
|
|
||||||
/// Type represent streaming payload
|
/// Type represent streaming payload
|
||||||
pub enum Payload<S = PayloadStream> {
|
pub enum Payload<S = PayloadStream> {
|
||||||
@ -48,18 +52,17 @@ impl<S> Payload<S> {
|
|||||||
|
|
||||||
impl<S> Stream for Payload<S>
|
impl<S> Stream for Payload<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
S: Stream<Item = Result<Bytes, PayloadError>> + Unpin,
|
||||||
{
|
{
|
||||||
type Item = Bytes;
|
type Item = Result<Bytes, PayloadError>;
|
||||||
type Error = PayloadError;
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||||
match self {
|
match self.get_mut() {
|
||||||
Payload::None => Ok(Async::Ready(None)),
|
Payload::None => Poll::Ready(None),
|
||||||
Payload::H1(ref mut pl) => pl.poll(),
|
Payload::H1(ref mut pl) => pl.readany(cx),
|
||||||
Payload::H2(ref mut pl) => pl.poll(),
|
Payload::H2(ref mut pl) => Pin::new(pl).poll_next(cx),
|
||||||
Payload::Stream(ref mut pl) => pl.poll(),
|
Payload::Stream(ref mut pl) => Pin::new(pl).poll_next(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use std::io::Write;
|
|||||||
use std::{fmt, str};
|
use std::{fmt, str};
|
||||||
|
|
||||||
use bytes::{BufMut, Bytes, BytesMut};
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
use futures::future::{ok, FutureResult, IntoFuture};
|
use futures::future::{ok, Ready};
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
@ -280,15 +280,15 @@ impl<B: MessageBody> fmt::Debug for Response<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoFuture for Response {
|
// impl IntoFuture for Response {
|
||||||
type Item = Response;
|
// type Item = Response;
|
||||||
type Error = Error;
|
// type Error = Error;
|
||||||
type Future = FutureResult<Response, Error>;
|
// type Future = FutureResult<Response, Error>;
|
||||||
|
|
||||||
fn into_future(self) -> Self::Future {
|
// fn into_future(self) -> Self::Future {
|
||||||
ok(self)
|
// ok(self)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub struct CookieIter<'a> {
|
pub struct CookieIter<'a> {
|
||||||
iter: header::GetAll<'a>,
|
iter: header::GetAll<'a>,
|
||||||
@ -635,8 +635,8 @@ impl ResponseBuilder {
|
|||||||
/// `ResponseBuilder` can not be used after this call.
|
/// `ResponseBuilder` can not be used after this call.
|
||||||
pub fn streaming<S, E>(&mut self, stream: S) -> Response
|
pub fn streaming<S, E>(&mut self, stream: S) -> Response
|
||||||
where
|
where
|
||||||
S: Stream<Item = Bytes, Error = E> + 'static,
|
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
|
||||||
E: Into<Error> + 'static,
|
E: Into<Error> + Unpin + 'static,
|
||||||
{
|
{
|
||||||
self.body(Body::from_message(BodyStream::new(stream)))
|
self.body(Body::from_message(BodyStream::new(stream)))
|
||||||
}
|
}
|
||||||
@ -757,15 +757,15 @@ impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoFuture for ResponseBuilder {
|
// impl IntoFuture for ResponseBuilder {
|
||||||
type Item = Response;
|
// type Item = Response;
|
||||||
type Error = Error;
|
// type Error = Error;
|
||||||
type Future = FutureResult<Response, Error>;
|
// type Future = FutureResult<Response, Error>;
|
||||||
|
|
||||||
fn into_future(mut self) -> Self::Future {
|
// fn into_future(mut self) -> Self::Future {
|
||||||
ok(self.finish())
|
// ok(self.finish())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl fmt::Debug for ResponseBuilder {
|
impl fmt::Debug for ResponseBuilder {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
use std::{fmt, io, net, rc};
|
use std::{fmt, io, net, rc};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
use actix_server_config::{
|
use actix_server_config::{
|
||||||
Io as ServerIo, IoStream, Protocol, ServerConfig as SrvConfig,
|
Io as ServerIo, IoStream, Protocol, ServerConfig as SrvConfig,
|
||||||
};
|
};
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
use actix_service::{IntoServiceFactory, Service, ServiceFactory};
|
||||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||||
use futures::{try_ready, Async, Future, IntoFuture, Poll};
|
use futures::{ready, Future};
|
||||||
use h2::server::{self, Handshake};
|
use h2::server::{self, Handshake};
|
||||||
|
|
||||||
use crate::body::MessageBody;
|
use crate::body::MessageBody;
|
||||||
@ -20,7 +22,7 @@ use crate::request::Request;
|
|||||||
use crate::response::Response;
|
use crate::response::Response;
|
||||||
use crate::{h1, h2::Dispatcher};
|
use crate::{h1, h2::Dispatcher};
|
||||||
|
|
||||||
/// `NewService` HTTP1.1/HTTP2 transport implementation
|
/// `ServiceFactory` HTTP1.1/HTTP2 transport implementation
|
||||||
pub struct HttpService<T, P, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler<T>> {
|
pub struct HttpService<T, P, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler<T>> {
|
||||||
srv: S,
|
srv: S,
|
||||||
cfg: ServiceConfig,
|
cfg: ServiceConfig,
|
||||||
@ -32,11 +34,13 @@ pub struct HttpService<T, P, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler
|
|||||||
|
|
||||||
impl<T, S, B> HttpService<T, (), S, B>
|
impl<T, S, B> HttpService<T, (), S, B>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
{
|
{
|
||||||
/// Create builder for `HttpService` instance.
|
/// Create builder for `HttpService` instance.
|
||||||
@ -47,20 +51,23 @@ where
|
|||||||
|
|
||||||
impl<T, P, S, B> HttpService<T, P, S, B>
|
impl<T, P, S, B> HttpService<T, P, S, B>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
/// Create new `HttpService` instance.
|
/// Create new `HttpService` instance.
|
||||||
pub fn new<F: IntoNewService<S>>(service: F) -> Self {
|
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self {
|
||||||
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0);
|
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0);
|
||||||
|
|
||||||
HttpService {
|
HttpService {
|
||||||
cfg,
|
cfg,
|
||||||
srv: service.into_new_service(),
|
srv: service.into_factory(),
|
||||||
expect: h1::ExpectHandler,
|
expect: h1::ExpectHandler,
|
||||||
upgrade: None,
|
upgrade: None,
|
||||||
on_connect: None,
|
on_connect: None,
|
||||||
@ -69,13 +76,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create new `HttpService` instance with config.
|
/// Create new `HttpService` instance with config.
|
||||||
pub(crate) fn with_config<F: IntoNewService<S>>(
|
pub(crate) fn with_config<F: IntoServiceFactory<S>>(
|
||||||
cfg: ServiceConfig,
|
cfg: ServiceConfig,
|
||||||
service: F,
|
service: F,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
HttpService {
|
HttpService {
|
||||||
cfg,
|
cfg,
|
||||||
srv: service.into_new_service(),
|
srv: service.into_factory(),
|
||||||
expect: h1::ExpectHandler,
|
expect: h1::ExpectHandler,
|
||||||
upgrade: None,
|
upgrade: None,
|
||||||
on_connect: None,
|
on_connect: None,
|
||||||
@ -86,11 +93,15 @@ where
|
|||||||
|
|
||||||
impl<T, P, S, B, X, U> HttpService<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> HttpService<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
/// Provide service for `EXPECT: 100-Continue` support.
|
/// Provide service for `EXPECT: 100-Continue` support.
|
||||||
///
|
///
|
||||||
@ -99,9 +110,12 @@ where
|
|||||||
/// request will be forwarded to main service.
|
/// request will be forwarded to main service.
|
||||||
pub fn expect<X1>(self, expect: X1) -> HttpService<T, P, S, B, X1, U>
|
pub fn expect<X1>(self, expect: X1) -> HttpService<T, P, S, B, X1, U>
|
||||||
where
|
where
|
||||||
X1: NewService<Config = SrvConfig, Request = Request, Response = Request>,
|
X1: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
|
||||||
X1::Error: Into<Error>,
|
X1::Error: Into<Error>,
|
||||||
X1::InitError: fmt::Debug,
|
X1::InitError: fmt::Debug,
|
||||||
|
X1::Future: Unpin,
|
||||||
|
X1::Service: Unpin,
|
||||||
|
<X1::Service as Service>::Future: Unpin + 'static,
|
||||||
{
|
{
|
||||||
HttpService {
|
HttpService {
|
||||||
expect,
|
expect,
|
||||||
@ -119,13 +133,16 @@ where
|
|||||||
/// and this service get called with original request and framed object.
|
/// and this service get called with original request and framed object.
|
||||||
pub fn upgrade<U1>(self, upgrade: Option<U1>) -> HttpService<T, P, S, B, X, U1>
|
pub fn upgrade<U1>(self, upgrade: Option<U1>) -> HttpService<T, P, S, B, X, U1>
|
||||||
where
|
where
|
||||||
U1: NewService<
|
U1: ServiceFactory<
|
||||||
Config = SrvConfig,
|
Config = SrvConfig,
|
||||||
Request = (Request, Framed<T, h1::Codec>),
|
Request = (Request, Framed<T, h1::Codec>),
|
||||||
Response = (),
|
Response = (),
|
||||||
>,
|
>,
|
||||||
U1::Error: fmt::Display,
|
U1::Error: fmt::Display,
|
||||||
U1::InitError: fmt::Debug,
|
U1::InitError: fmt::Debug,
|
||||||
|
U1::Future: Unpin,
|
||||||
|
U1::Service: Unpin,
|
||||||
|
<U1::Service as Service>::Future: Unpin + 'static,
|
||||||
{
|
{
|
||||||
HttpService {
|
HttpService {
|
||||||
upgrade,
|
upgrade,
|
||||||
@ -147,25 +164,35 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> NewService for HttpService<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> ServiceFactory for HttpService<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream + Unpin,
|
||||||
S: NewService<Config = SrvConfig, Request = Request>,
|
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Service: Unpin,
|
||||||
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
X: NewService<Config = SrvConfig, Request = Request, Response = Request>,
|
X: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
X::InitError: fmt::Debug,
|
X::InitError: fmt::Debug,
|
||||||
U: NewService<
|
X::Future: Unpin,
|
||||||
|
X::Service: Unpin,
|
||||||
|
<X::Service as Service>::Future: Unpin + 'static,
|
||||||
|
U: ServiceFactory<
|
||||||
Config = SrvConfig,
|
Config = SrvConfig,
|
||||||
Request = (Request, Framed<T, h1::Codec>),
|
Request = (Request, Framed<T, h1::Codec>),
|
||||||
Response = (),
|
Response = (),
|
||||||
>,
|
>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
U::InitError: fmt::Debug,
|
U::InitError: fmt::Debug,
|
||||||
|
U::Future: Unpin,
|
||||||
|
U::Service: Unpin,
|
||||||
|
<U::Service as Service>::Future: Unpin + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Config = SrvConfig;
|
type Config = SrvConfig;
|
||||||
type Request = ServerIo<T, P>;
|
type Request = ServerIo<T, P>;
|
||||||
@ -177,7 +204,7 @@ where
|
|||||||
|
|
||||||
fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
|
fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
|
||||||
HttpServiceResponse {
|
HttpServiceResponse {
|
||||||
fut: self.srv.new_service(cfg).into_future(),
|
fut: self.srv.new_service(cfg),
|
||||||
fut_ex: Some(self.expect.new_service(cfg)),
|
fut_ex: Some(self.expect.new_service(cfg)),
|
||||||
fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)),
|
fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)),
|
||||||
expect: None,
|
expect: None,
|
||||||
@ -190,7 +217,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct HttpServiceResponse<T, P, S: NewService, B, X: NewService, U: NewService> {
|
pub struct HttpServiceResponse<
|
||||||
|
T,
|
||||||
|
P,
|
||||||
|
S: ServiceFactory,
|
||||||
|
B,
|
||||||
|
X: ServiceFactory,
|
||||||
|
U: ServiceFactory,
|
||||||
|
> {
|
||||||
fut: S::Future,
|
fut: S::Future,
|
||||||
fut_ex: Option<X::Future>,
|
fut_ex: Option<X::Future>,
|
||||||
fut_upg: Option<U::Future>,
|
fut_upg: Option<U::Future>,
|
||||||
@ -204,50 +238,62 @@ pub struct HttpServiceResponse<T, P, S: NewService, B, X: NewService, U: NewServ
|
|||||||
impl<T, P, S, B, X, U> Future for HttpServiceResponse<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Future for HttpServiceResponse<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream,
|
||||||
S: NewService<Request = Request>,
|
S: ServiceFactory<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
<S::Service as Service>::Future: 'static,
|
S::Future: Unpin,
|
||||||
|
S::Service: Unpin,
|
||||||
|
<S::Service as Service>::Future: Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
X: NewService<Request = Request, Response = Request>,
|
X: ServiceFactory<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
X::InitError: fmt::Debug,
|
X::InitError: fmt::Debug,
|
||||||
U: NewService<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
X::Future: Unpin,
|
||||||
|
X::Service: Unpin,
|
||||||
|
<X::Service as Service>::Future: Unpin + 'static,
|
||||||
|
U: ServiceFactory<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
U::InitError: fmt::Debug,
|
U::InitError: fmt::Debug,
|
||||||
|
U::Future: Unpin,
|
||||||
|
U::Service: Unpin,
|
||||||
|
<U::Service as Service>::Future: Unpin + 'static,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Item = HttpServiceHandler<T, P, S::Service, B, X::Service, U::Service>;
|
type Output =
|
||||||
type Error = ();
|
Result<HttpServiceHandler<T, P, S::Service, B, X::Service, U::Service>, ()>;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
if let Some(ref mut fut) = self.fut_ex {
|
let this = self.get_mut();
|
||||||
let expect = try_ready!(fut
|
|
||||||
.poll()
|
if let Some(ref mut fut) = this.fut_ex {
|
||||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
let expect = ready!(Pin::new(fut)
|
||||||
self.expect = Some(expect);
|
.poll(cx)
|
||||||
self.fut_ex.take();
|
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||||
|
this.expect = Some(expect);
|
||||||
|
this.fut_ex.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut fut) = self.fut_upg {
|
if let Some(ref mut fut) = this.fut_upg {
|
||||||
let upgrade = try_ready!(fut
|
let upgrade = ready!(Pin::new(fut)
|
||||||
.poll()
|
.poll(cx)
|
||||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||||
self.upgrade = Some(upgrade);
|
this.upgrade = Some(upgrade);
|
||||||
self.fut_ex.take();
|
this.fut_ex.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
let service = try_ready!(self
|
let result = ready!(Pin::new(&mut this.fut)
|
||||||
.fut
|
.poll(cx)
|
||||||
.poll()
|
|
||||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
||||||
Ok(Async::Ready(HttpServiceHandler::new(
|
Poll::Ready(result.map(|service| {
|
||||||
self.cfg.take().unwrap(),
|
HttpServiceHandler::new(
|
||||||
service,
|
this.cfg.take().unwrap(),
|
||||||
self.expect.take().unwrap(),
|
service,
|
||||||
self.upgrade.take(),
|
this.expect.take().unwrap(),
|
||||||
self.on_connect.clone(),
|
this.upgrade.take(),
|
||||||
)))
|
this.on_connect.clone(),
|
||||||
|
)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,15 +309,19 @@ pub struct HttpServiceHandler<T, P, S, B, X, U> {
|
|||||||
|
|
||||||
impl<T, P, S, B, X, U> HttpServiceHandler<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> HttpServiceHandler<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request> + Unpin,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
|
S::Future: Unpin,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request> + Unpin,
|
||||||
|
X::Future: Unpin,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||||
|
U::Future: Unpin,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
fn new(
|
fn new(
|
||||||
cfg: ServiceConfig,
|
cfg: ServiceConfig,
|
||||||
@ -293,26 +343,29 @@ where
|
|||||||
|
|
||||||
impl<T, P, S, B, X, U> Service for HttpServiceHandler<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Service for HttpServiceHandler<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream + Unpin,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request> + Unpin,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request> + Unpin,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
X::Future: Unpin,
|
||||||
|
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
|
P: Unpin,
|
||||||
{
|
{
|
||||||
type Request = ServerIo<T, P>;
|
type Request = ServerIo<T, P>;
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = DispatchError;
|
type Error = DispatchError;
|
||||||
type Future = HttpServiceHandlerResponse<T, S, B, X, U>;
|
type Future = HttpServiceHandlerResponse<T, S, B, X, U>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||||
let ready = self
|
let ready = self
|
||||||
.expect
|
.expect
|
||||||
.poll_ready()
|
.poll_ready(cx)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
let e = e.into();
|
let e = e.into();
|
||||||
log::error!("Http service readiness error: {:?}", e);
|
log::error!("Http service readiness error: {:?}", e);
|
||||||
@ -322,7 +375,7 @@ where
|
|||||||
|
|
||||||
let ready = self
|
let ready = self
|
||||||
.srv
|
.srv
|
||||||
.poll_ready()
|
.poll_ready(cx)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
let e = e.into();
|
let e = e.into();
|
||||||
log::error!("Http service readiness error: {:?}", e);
|
log::error!("Http service readiness error: {:?}", e);
|
||||||
@ -332,9 +385,9 @@ where
|
|||||||
&& ready;
|
&& ready;
|
||||||
|
|
||||||
if ready {
|
if ready {
|
||||||
Ok(Async::Ready(()))
|
Poll::Ready(Ok(()))
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::NotReady)
|
Poll::Pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,15 +444,17 @@ where
|
|||||||
|
|
||||||
enum State<T, S, B, X, U>
|
enum State<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request> + Unpin,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
T: IoStream,
|
T: IoStream + Unpin,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request> + Unpin,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
X::Future: Unpin,
|
||||||
|
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
H1(h1::Dispatcher<T, S, B, X, U>),
|
H1(h1::Dispatcher<T, S, B, X, U>),
|
||||||
H2(Dispatcher<Io<T>, S, B>),
|
H2(Dispatcher<Io<T>, S, B>),
|
||||||
@ -427,16 +482,18 @@ where
|
|||||||
|
|
||||||
pub struct HttpServiceHandlerResponse<T, S, B, X, U>
|
pub struct HttpServiceHandlerResponse<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream + Unpin,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request> + Unpin,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request> + Unpin,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
X::Future: Unpin,
|
||||||
|
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
|
U::Future: Unpin,
|
||||||
{
|
{
|
||||||
state: State<T, S, B, X, U>,
|
state: State<T, S, B, X, U>,
|
||||||
}
|
}
|
||||||
@ -445,32 +502,33 @@ const HTTP2_PREFACE: [u8; 14] = *b"PRI * HTTP/2.0";
|
|||||||
|
|
||||||
impl<T, S, B, X, U> Future for HttpServiceHandlerResponse<T, S, B, X, U>
|
impl<T, S, B, X, U> Future for HttpServiceHandlerResponse<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: IoStream,
|
T: IoStream + Unpin,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request> + Unpin,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error> + Unpin + 'static,
|
||||||
S::Future: 'static,
|
S::Future: Unpin + 'static,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>> + Unpin + 'static,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request> + Unpin,
|
||||||
|
X::Future: Unpin,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()> + Unpin,
|
||||||
|
U::Future: Unpin,
|
||||||
U::Error: fmt::Display,
|
U::Error: fmt::Display,
|
||||||
{
|
{
|
||||||
type Item = ();
|
type Output = Result<(), DispatchError>;
|
||||||
type Error = DispatchError;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::H1(ref mut disp) => disp.poll(),
|
State::H1(ref mut disp) => Pin::new(disp).poll(cx),
|
||||||
State::H2(ref mut disp) => disp.poll(),
|
State::H2(ref mut disp) => Pin::new(disp).poll(cx),
|
||||||
State::Unknown(ref mut data) => {
|
State::Unknown(ref mut data) => {
|
||||||
if let Some(ref mut item) = data {
|
if let Some(ref mut item) = data {
|
||||||
loop {
|
loop {
|
||||||
// Safety - we only write to the returned slice.
|
// Safety - we only write to the returned slice.
|
||||||
let b = unsafe { item.1.bytes_mut() };
|
let b = unsafe { item.1.bytes_mut() };
|
||||||
let n = try_ready!(item.0.poll_read(b));
|
let n = ready!(Pin::new(&mut item.0).poll_read(cx, b))?;
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return Ok(Async::Ready(()));
|
return Poll::Ready(Ok(()));
|
||||||
}
|
}
|
||||||
// Safety - we know that 'n' bytes have
|
// Safety - we know that 'n' bytes have
|
||||||
// been initialized via the contract of
|
// been initialized via the contract of
|
||||||
@ -511,17 +569,17 @@ where
|
|||||||
on_connect,
|
on_connect,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
self.poll()
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
State::Handshake(ref mut data) => {
|
State::Handshake(ref mut data) => {
|
||||||
let conn = if let Some(ref mut item) = data {
|
let conn = if let Some(ref mut item) = data {
|
||||||
match item.0.poll() {
|
match Pin::new(&mut item.0).poll(cx) {
|
||||||
Ok(Async::Ready(conn)) => conn,
|
Poll::Ready(Ok(conn)) => conn,
|
||||||
Ok(Async::NotReady) => return Ok(Async::NotReady),
|
Poll::Ready(Err(err)) => {
|
||||||
Err(err) => {
|
|
||||||
trace!("H2 handshake error: {}", err);
|
trace!("H2 handshake error: {}", err);
|
||||||
return Err(err.into());
|
return Poll::Ready(Err(err.into()));
|
||||||
}
|
}
|
||||||
|
Poll::Pending => return Poll::Pending,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
@ -530,7 +588,7 @@ where
|
|||||||
self.state = State::H2(Dispatcher::new(
|
self.state = State::H2(Dispatcher::new(
|
||||||
srv, conn, on_connect, cfg, None, peer_addr,
|
srv, conn, on_connect, cfg, None, peer_addr,
|
||||||
));
|
));
|
||||||
self.poll()
|
self.poll(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,6 +600,8 @@ struct Io<T> {
|
|||||||
inner: T,
|
inner: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Unpin for Io<T> {}
|
||||||
|
|
||||||
impl<T: io::Read> io::Read for Io<T> {
|
impl<T: io::Read> io::Read for Io<T> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
if let Some(mut bytes) = self.unread.take() {
|
if let Some(mut bytes) = self.unread.take() {
|
||||||
@ -567,22 +627,62 @@ impl<T: io::Write> io::Write for Io<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsyncRead> AsyncRead for Io<T> {
|
impl<T: AsyncRead + Unpin> AsyncRead for Io<T> {
|
||||||
|
// unsafe fn initializer(&self) -> io::Initializer {
|
||||||
|
// self.get_mut().inner.initializer()
|
||||||
|
// }
|
||||||
|
|
||||||
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
|
unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
|
||||||
self.inner.prepare_uninitialized_buffer(buf)
|
self.inner.prepare_uninitialized_buffer(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll_read(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &mut [u8],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut self.get_mut().inner).poll_read(cx, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn poll_read_vectored(
|
||||||
|
// self: Pin<&mut Self>,
|
||||||
|
// cx: &mut Context<'_>,
|
||||||
|
// bufs: &mut [io::IoSliceMut<'_>],
|
||||||
|
// ) -> Poll<io::Result<usize>> {
|
||||||
|
// self.get_mut().inner.poll_read_vectored(cx, bufs)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsyncWrite> AsyncWrite for Io<T> {
|
impl<T: AsyncWrite + Unpin> tokio_io::AsyncWrite for Io<T> {
|
||||||
fn shutdown(&mut self) -> Poll<(), io::Error> {
|
fn poll_write(
|
||||||
self.inner.shutdown()
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut self.get_mut().inner).poll_write(cx, buf)
|
||||||
}
|
}
|
||||||
fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
|
|
||||||
self.inner.write_buf(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)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_shutdown(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut self.get_mut().inner).poll_shutdown(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IoStream> IoStream for Io<T> {
|
impl<T: IoStream> actix_server_config::IoStream for Io<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn peer_addr(&self) -> Option<net::SocketAddr> {
|
fn peer_addr(&self) -> Option<net::SocketAddr> {
|
||||||
self.inner.peer_addr()
|
self.inner.peer_addr()
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
//! Test Various helpers for Actix applications to use during testing.
|
//! Test Various helpers for Actix applications to use during testing.
|
||||||
use std::fmt::Write as FmtWrite;
|
use std::fmt::Write as FmtWrite;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::pin::Pin;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
use actix_server_config::IoStream;
|
use actix_server_config::IoStream;
|
||||||
use bytes::{Buf, Bytes, BytesMut};
|
use bytes::{Buf, Bytes, BytesMut};
|
||||||
use futures::{Async, Poll};
|
|
||||||
use http::header::{self, HeaderName, HeaderValue};
|
use http::header::{self, HeaderName, HeaderValue};
|
||||||
use http::{HttpTryFrom, Method, Uri, Version};
|
use http::{HttpTryFrom, Method, Uri, Version};
|
||||||
use percent_encoding::percent_encode;
|
use percent_encoding::percent_encode;
|
||||||
@ -244,16 +245,16 @@ impl io::Write for TestBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncRead for TestBuffer {}
|
// impl AsyncRead for TestBuffer {}
|
||||||
|
|
||||||
impl AsyncWrite for TestBuffer {
|
// impl AsyncWrite for TestBuffer {
|
||||||
fn shutdown(&mut self) -> Poll<(), io::Error> {
|
// fn shutdown(&mut self) -> Poll<(), io::Error> {
|
||||||
Ok(Async::Ready(()))
|
// Ok(Async::Ready(()))
|
||||||
}
|
// }
|
||||||
fn write_buf<B: Buf>(&mut self, _: &mut B) -> Poll<usize, io::Error> {
|
// fn write_buf<B: Buf>(&mut self, _: &mut B) -> Poll<usize, io::Error> {
|
||||||
Ok(Async::NotReady)
|
// Ok(Async::NotReady)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl IoStream for TestBuffer {
|
impl IoStream for TestBuffer {
|
||||||
fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> {
|
fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> {
|
||||||
|
Loading…
Reference in New Issue
Block a user