1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-30 18:44:35 +01:00
Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
fakeshadow 2021-01-04 07:47:04 +08:00 committed by GitHub
parent 1f202d40e4
commit 32de9f8840
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 788 additions and 826 deletions

View File

@ -2,10 +2,15 @@
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
### Changed ### Changed
* Bumped `rand` to `0.8` * Update `actix-*` dependencies to tokio `1.0` based versions. [#1813]
* Bumped `rand` to `0.8`.
* Update `rust-tls` to `0.19`. [#1813]
* Rename `Handler` to `HandlerService` and rename `Factory` to `Handler`. [#1852] * Rename `Handler` to `HandlerService` and rename `Factory` to `Handler`. [#1852]
* MSRV is now 1.46.0. * MSRV is now 1.46.0.
[#1813]: https://github.com/actix/actix-web/pull/1813
### Fixed ### Fixed
* added the actual parsing error to `test::read_body_json` [#1812] * added the actual parsing error to `test::read_body_json` [#1812]

View File

@ -47,10 +47,10 @@ compress = ["actix-http/compress", "awc/compress"]
secure-cookies = ["actix-http/secure-cookies"] secure-cookies = ["actix-http/secure-cookies"]
# openssl # openssl
openssl = ["actix-tls/openssl", "awc/openssl", "open-ssl"] openssl = ["actix-tls/accept", "actix-tls/openssl", "awc/openssl", "open-ssl"]
# rustls # rustls
rustls = ["actix-tls/rustls", "awc/rustls", "rust-tls"] rustls = ["actix-tls/accept", "actix-tls/rustls", "awc/rustls", "rust-tls"]
[[example]] [[example]]
name = "basic" name = "basic"
@ -73,27 +73,25 @@ name = "client"
required-features = ["rustls"] required-features = ["rustls"]
[dependencies] [dependencies]
actix-codec = "0.3.0" actix-codec = "0.4.0-beta.1"
actix-service = "1.0.6"
actix-utils = "2.0.0"
actix-router = "0.2.4"
actix-rt = "1.1.1"
actix-server = "1.0.0"
actix-testing = "1.0.0"
actix-macros = "0.1.0" actix-macros = "0.1.0"
actix-router = "0.2.4"
actix-rt = "2.0.0-beta.1"
actix-server = "2.0.0-beta.2"
actix-service = "2.0.0-beta.2"
actix-utils = "3.0.0-beta.1"
actix-threadpool = "0.3.1" actix-threadpool = "0.3.1"
actix-tls = "2.0.0" actix-tls = { version = "3.0.0-beta.2", default-features = false, optional = true }
actix-web-codegen = "0.4.0" actix-web-codegen = "0.4.0"
actix-http = "2.2.0" actix-http = "2.2.0"
awc = { version = "2.0.3", default-features = false } awc = { version = "2.0.3", default-features = false }
bytes = "0.5.3" bytes = "1"
derive_more = "0.99.5" derive_more = "0.99.5"
encoding_rs = "0.8" encoding_rs = "0.8"
futures-channel = { version = "0.3.5", default-features = false } futures-core = { version = "0.3.7", default-features = false }
futures-core = { version = "0.3.5", default-features = false } futures-util = { version = "0.3.7", default-features = false }
futures-util = { version = "0.3.5", default-features = false }
fxhash = "0.2.1" fxhash = "0.2.1"
log = "0.4" log = "0.4"
mime = "0.3" mime = "0.3"
@ -106,12 +104,12 @@ serde_urlencoded = "0.7"
time = { version = "0.2.7", default-features = false, features = ["std"] } time = { version = "0.2.7", default-features = false, features = ["std"] }
url = "2.1" url = "2.1"
open-ssl = { package = "openssl", version = "0.10", optional = true } open-ssl = { package = "openssl", version = "0.10", optional = true }
rust-tls = { package = "rustls", version = "0.18.0", optional = true } rust-tls = { package = "rustls", version = "0.19.0", optional = true }
smallvec = "1.6" smallvec = "1.6"
[dev-dependencies] [dev-dependencies]
actix = "0.10.0" actix = "0.11.0-beta.1"
actix-http = { version = "2.1.0", features = ["actors"] } actix-http = { version = "2.2.0", features = ["actors"] }
rand = "0.8" rand = "0.8"
env_logger = "0.8" env_logger = "0.8"
serde_derive = "1.0" serde_derive = "1.0"

View File

@ -2,6 +2,9 @@
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
* `HttpRange::parse` now has its own error type. * `HttpRange::parse` now has its own error type.
* Update `bytes` to `1.0`. [#1813]
[#1813]: https://github.com/actix/actix-web/pull/1813
## 0.5.0 - 2020-12-26 ## 0.5.0 - 2020-12-26

View File

@ -18,9 +18,9 @@ path = "src/lib.rs"
[dependencies] [dependencies]
actix-web = { version = "3.0.0", default-features = false } actix-web = { version = "3.0.0", default-features = false }
actix-service = "1.0.6" actix-service = "2.0.0-beta.2"
bitflags = "1" bitflags = "1"
bytes = "0.5.3" bytes = "1"
futures-core = { version = "0.3.7", default-features = false } futures-core = { version = "0.3.7", default-features = false }
futures-util = { version = "0.3.7", default-features = false } futures-util = { version = "0.3.7", default-features = false }
derive_more = "0.99.5" derive_more = "0.99.5"
@ -31,5 +31,5 @@ percent-encoding = "2.1"
v_htmlescape = "0.12" v_htmlescape = "0.12"
[dev-dependencies] [dev-dependencies]
actix-rt = "1.0.0" actix-rt = "2.0.0-beta.1"
actix-web = "3.0.0" actix-web = "3.0.0"

View File

@ -1,6 +1,6 @@
use std::{cell::RefCell, fmt, io, path::PathBuf, rc::Rc}; use std::{cell::RefCell, fmt, io, path::PathBuf, rc::Rc};
use actix_service::{boxed, IntoServiceFactory, ServiceFactory}; use actix_service::{boxed, IntoServiceFactory, ServiceFactory, ServiceFactoryExt};
use actix_web::{ use actix_web::{
dev::{ dev::{
AppService, HttpServiceFactory, ResourceDef, ServiceRequest, ServiceResponse, AppService, HttpServiceFactory, ResourceDef, ServiceRequest, ServiceResponse,
@ -201,10 +201,10 @@ impl Files {
/// Sets default handler which is used when no matched file could be found. /// Sets default handler which is used when no matched file could be found.
pub fn default_handler<F, U>(mut self, f: F) -> Self pub fn default_handler<F, U>(mut self, f: F) -> Self
where where
F: IntoServiceFactory<U>, F: IntoServiceFactory<U, ServiceRequest>,
U: ServiceFactory< U: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
> + 'static, > + 'static,
@ -241,8 +241,7 @@ impl HttpServiceFactory for Files {
} }
} }
impl ServiceFactory for Files { impl ServiceFactory<ServiceRequest> for Files {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Config = (); type Config = ();

View File

@ -57,8 +57,7 @@ impl fmt::Debug for FilesService {
} }
} }
impl Service for FilesService { impl Service<ServiceRequest> for FilesService {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = FilesServiceFuture; type Future = FilesServiceFuture;

View File

@ -1,6 +1,9 @@
# Changes # Changes
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
* Update `bytes` to `1.0`. [#1813]
[#1813]: https://github.com/actix/actix-web/pull/1813
## 2.1.0 - 2020-11-25 ## 2.1.0 - 2020-11-25

View File

@ -29,19 +29,18 @@ default = []
openssl = ["open-ssl", "awc/openssl"] openssl = ["open-ssl", "awc/openssl"]
[dependencies] [dependencies]
actix-service = "1.0.6" actix-service = "2.0.0-beta.2"
actix-codec = "0.3.0" actix-codec = "0.4.0-beta.1"
actix-connect = "2.0.0" actix-tls = "3.0.0-beta.2"
actix-utils = "2.0.0" actix-utils = "3.0.0-beta.1"
actix-rt = "1.1.1" actix-rt = "2.0.0-beta.1"
actix-server = "1.0.0" actix-server = "2.0.0-beta.2"
actix-testing = "1.0.0"
awc = "2.0.0" awc = "2.0.0"
base64 = "0.13" base64 = "0.13"
bytes = "0.5.3" bytes = "1"
futures-core = { version = "0.3.5", default-features = false } futures-core = { version = "0.3.7", default-features = false }
http = "0.2.0" http = "0.2.2"
log = "0.4" log = "0.4"
socket2 = "0.3" socket2 = "0.3"
serde = "1.0" serde = "1.0"

View File

@ -16,8 +16,6 @@ use futures_core::stream::Stream;
use http::Method; use http::Method;
use socket2::{Domain, Protocol, Socket, Type}; use socket2::{Domain, Protocol, Socket, Type};
pub use actix_testing::*;
/// Start test server /// Start test server
/// ///
/// `TestServer` is very simple test server that simplify process of writing /// `TestServer` is very simple test server that simplify process of writing
@ -65,13 +63,16 @@ pub async fn test_server_with_addr<F: ServiceFactory<TcpStream>>(
let sys = System::new("actix-test-server"); let sys = System::new("actix-test-server");
let local_addr = tcp.local_addr().unwrap(); let local_addr = tcp.local_addr().unwrap();
Server::build() let srv = Server::build()
.listen("test", tcp, factory)? .listen("test", tcp, factory)?
.workers(1) .workers(1)
.disable_signals() .disable_signals();
.start();
sys.block_on(async {
srv.start();
tx.send((System::current(), local_addr)).unwrap();
});
tx.send((System::current(), local_addr)).unwrap();
sys.run() sys.run()
}); });
@ -105,7 +106,7 @@ pub async fn test_server_with_addr<F: ServiceFactory<TcpStream>>(
Client::builder().connector(connector).finish() Client::builder().connector(connector).finish()
}; };
actix_connect::start_default_resolver().await.unwrap(); actix_tls::connect::start_default_resolver().await.unwrap();
TestServer { TestServer {
addr, addr,

View File

@ -2,13 +2,25 @@
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
### Changed ### Changed
* Bumped `rand` to `0.8` * Bumped `rand` to `0.8`.
* Update `actix-*` dependencies to tokio `1.0` based versions. [#1813]
* Update `bytes` to `1.0`. [#1813]
* Update `h2` to `0.3`. [#1813]
[#1813]: https://github.com/actix/actix-web/pull/1813
### Removed ### Removed
* Deprecated `on_connect` methods have been removed. Prefer the new * Deprecated `on_connect` methods have been removed. Prefer the new
`on_connect_ext` technique. [#1857] `on_connect_ext` technique. [#1857]
* Remove `ResponseError` impl for `actix::actors::resolver::ResolverError`
due to deprecate of resolver actor. [#1813]
* Remove `ConnectError::SslHandshakeError` and re-export of `HandshakeError`.
due to the removal of this type from `tokio-openssl` crate. openssl handshake
error would return as `ConnectError::SslError`. [#1813]
[#1813]: https://github.com/actix/actix-web/pull/1813
[#1857]: https://github.com/actix/actix-web/pull/1857 [#1857]: https://github.com/actix/actix-web/pull/1857

View File

@ -25,10 +25,10 @@ path = "src/lib.rs"
default = [] default = []
# openssl # openssl
openssl = ["actix-tls/openssl", "actix-connect/openssl"] openssl = ["actix-tls/openssl"]
# rustls support # rustls support
rustls = ["actix-tls/rustls", "actix-connect/rustls"] rustls = ["actix-tls/rustls"]
# enable compressison support # enable compressison support
compress = ["flate2", "brotli2"] compress = ["flate2", "brotli2"]
@ -40,29 +40,28 @@ secure-cookies = ["cookie/secure"]
actors = ["actix"] actors = ["actix"]
[dependencies] [dependencies]
actix-service = "1.0.6" actix-service = "2.0.0-beta.2"
actix-codec = "0.3.0" actix-codec = "0.4.0-beta.1"
actix-connect = "2.0.0" actix-utils = "3.0.0-beta.1"
actix-utils = "2.0.0" actix-rt = "2.0.0-beta.1"
actix-rt = "1.0.0"
actix-threadpool = "0.3.1" actix-threadpool = "0.3.1"
actix-tls = { version = "2.0.0", optional = true } actix-tls = "3.0.0-beta.2"
actix = { version = "0.10.0", optional = true } actix = { version = "0.11.0-beta.1", optional = true }
base64 = "0.13" base64 = "0.13"
bitflags = "1.2" bitflags = "1.2"
bytes = "0.5.3" bytes = "1"
cookie = { version = "0.14.1", features = ["percent-encode"] } cookie = { version = "0.14.1", features = ["percent-encode"] }
copyless = "0.1.4" copyless = "0.1.4"
derive_more = "0.99.2" derive_more = "0.99.2"
either = "1.5.3" either = "1.5.3"
encoding_rs = "0.8" encoding_rs = "0.8"
futures-channel = { version = "0.3.5", default-features = false } futures-channel = { version = "0.3.7", default-features = false }
futures-core = { version = "0.3.5", default-features = false } futures-core = { version = "0.3.7", default-features = false }
futures-util = { version = "0.3.5", default-features = false } futures-util = { version = "0.3.7", default-features = false, features = ["sink"] }
fxhash = "0.2.1" fxhash = "0.2.1"
h2 = "0.2.1" h2 = "0.3.0"
http = "0.2.0" http = "0.2.2"
httparse = "1.3" httparse = "1.3"
indexmap = "1.3" indexmap = "1.3"
itoa = "0.4" itoa = "0.4"
@ -86,15 +85,14 @@ brotli2 = { version="0.3.2", optional = true }
flate2 = { version = "1.0.13", optional = true } flate2 = { version = "1.0.13", optional = true }
[dev-dependencies] [dev-dependencies]
actix-server = "1.0.1" actix-server = "2.0.0-beta.2"
actix-connect = { version = "2.0.0", features = ["openssl"] }
actix-http-test = { version = "2.0.0", features = ["openssl"] } actix-http-test = { version = "2.0.0", features = ["openssl"] }
actix-tls = { version = "2.0.0", features = ["openssl"] } actix-tls = { version = "3.0.0-beta.2", features = ["openssl"] }
criterion = "0.3" criterion = "0.3"
env_logger = "0.7" env_logger = "0.7"
serde_derive = "1.0" serde_derive = "1.0"
open-ssl = { version="0.10", package = "openssl" } open-ssl = { version="0.10", package = "openssl" }
rust-tls = { version="0.18", package = "rustls" } rust-tls = { version="0.19", package = "rustls" }
[[bench]] [[bench]]
name = "write-camel-case" name = "write-camel-case"

View File

@ -19,7 +19,7 @@ use crate::{ConnectCallback, Extensions};
/// ///
/// This type can be used to construct an instance of [`HttpService`] through a /// This type can be used to construct an instance of [`HttpService`] through a
/// builder-like pattern. /// builder-like pattern.
pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler<T>> { pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler> {
keep_alive: KeepAlive, keep_alive: KeepAlive,
client_timeout: u64, client_timeout: u64,
client_disconnect: u64, client_disconnect: u64,
@ -28,15 +28,15 @@ pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler<T>> {
expect: X, expect: X,
upgrade: Option<U>, upgrade: Option<U>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>, on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<(T, S)>, _t: PhantomData<S>,
} }
impl<T, S> HttpServiceBuilder<T, S, ExpectHandler, UpgradeHandler<T>> impl<T, S> HttpServiceBuilder<T, S, ExpectHandler, UpgradeHandler>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
{ {
/// Create instance of `ServiceConfigBuilder` /// Create instance of `ServiceConfigBuilder`
pub fn new() -> Self { pub fn new() -> Self {
@ -56,18 +56,18 @@ where
impl<T, S, X, U> HttpServiceBuilder<T, S, X, U> impl<T, S, X, U> HttpServiceBuilder<T, S, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
<X::Service as Service>::Future: 'static, <X::Service as Service<Request>>::Future: 'static,
U: ServiceFactory<Config = (), Request = (Request, Framed<T, Codec>), Response = ()>, U: ServiceFactory<(Request, Framed<T, Codec>), Config = (), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
<U::Service as Service>::Future: 'static, <U::Service as Service<(Request, Framed<T, Codec>)>>::Future: 'static,
{ {
/// Set server keep-alive setting. /// Set server keep-alive setting.
/// ///
@ -123,11 +123,11 @@ 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: IntoServiceFactory<X1>, F: IntoServiceFactory<X1, Request>,
X1: ServiceFactory<Config = (), Request = Request, Response = Request>, X1: ServiceFactory<Request, Config = (), Response = Request>,
X1::Error: Into<Error>, X1::Error: Into<Error>,
X1::InitError: fmt::Debug, X1::InitError: fmt::Debug,
<X1::Service as Service>::Future: 'static, <X1::Service as Service<Request>>::Future: 'static,
{ {
HttpServiceBuilder { HttpServiceBuilder {
keep_alive: self.keep_alive, keep_alive: self.keep_alive,
@ -148,15 +148,11 @@ 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: IntoServiceFactory<U1>, F: IntoServiceFactory<U1, (Request, Framed<T, Codec>)>,
U1: ServiceFactory< U1: ServiceFactory<(Request, Framed<T, Codec>), Config = (), Response = ()>,
Config = (),
Request = (Request, Framed<T, Codec>),
Response = (),
>,
U1::Error: fmt::Display, U1::Error: fmt::Display,
U1::InitError: fmt::Debug, U1::InitError: fmt::Debug,
<U1::Service as Service>::Future: 'static, <U1::Service as Service<(Request, Framed<T, Codec>)>>::Future: 'static,
{ {
HttpServiceBuilder { HttpServiceBuilder {
keep_alive: self.keep_alive, keep_alive: self.keep_alive,
@ -188,7 +184,7 @@ where
pub fn h1<F, B>(self, service: F) -> H1Service<T, S, B, X, U> pub fn h1<F, B>(self, service: F) -> H1Service<T, S, B, X, U>
where where
B: MessageBody, B: MessageBody,
F: IntoServiceFactory<S>, F: IntoServiceFactory<S, 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>>,
@ -211,11 +207,11 @@ where
pub fn h2<F, B>(self, service: F) -> H2Service<T, S, B> pub fn h2<F, B>(self, service: F) -> H2Service<T, S, B>
where where
B: MessageBody + 'static, B: MessageBody + 'static,
F: IntoServiceFactory<S>, F: IntoServiceFactory<S, Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
{ {
let cfg = ServiceConfig::new( let cfg = ServiceConfig::new(
self.keep_alive, self.keep_alive,
@ -233,11 +229,11 @@ where
pub fn finish<F, B>(self, service: F) -> HttpService<T, S, B, X, U> pub fn finish<F, B>(self, service: F) -> HttpService<T, S, B, X, U>
where where
B: MessageBody + 'static, B: MessageBody + 'static,
F: IntoServiceFactory<S>, F: IntoServiceFactory<S, Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
{ {
let cfg = ServiceConfig::new( let cfg = ServiceConfig::new(
self.keep_alive, self.keep_alive,

View File

@ -1,10 +1,10 @@
use std::future::Future; use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::{fmt, io, mem, time}; use std::{fmt, io, time};
use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_codec::{AsyncRead, AsyncWrite, Framed, ReadBuf};
use bytes::{Buf, Bytes}; use bytes::Bytes;
use futures_util::future::{err, Either, FutureExt, LocalBoxFuture, Ready}; use futures_util::future::{err, Either, FutureExt, LocalBoxFuture, Ready};
use h2::client::SendRequest; use h2::client::SendRequest;
use pin_project::pin_project; use pin_project::pin_project;
@ -223,23 +223,13 @@ where
fn poll_read( fn poll_read(
self: Pin<&mut Self>, self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,
buf: &mut [u8], buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<usize>> { ) -> Poll<io::Result<()>> {
match self.project() { match self.project() {
EitherIoProj::A(val) => val.poll_read(cx, buf), EitherIoProj::A(val) => val.poll_read(cx, buf),
EitherIoProj::B(val) => val.poll_read(cx, buf), EitherIoProj::B(val) => val.poll_read(cx, buf),
} }
} }
unsafe fn prepare_uninitialized_buffer(
&self,
buf: &mut [mem::MaybeUninit<u8>],
) -> bool {
match self {
EitherIo::A(ref val) => val.prepare_uninitialized_buffer(buf),
EitherIo::B(ref val) => val.prepare_uninitialized_buffer(buf),
}
}
} }
impl<A, B> AsyncWrite for EitherIo<A, B> impl<A, B> AsyncWrite for EitherIo<A, B>
@ -274,18 +264,4 @@ where
EitherIoProj::B(val) => val.poll_shutdown(cx), EitherIoProj::B(val) => val.poll_shutdown(cx),
} }
} }
fn poll_write_buf<U: Buf>(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut U,
) -> Poll<Result<usize, io::Error>>
where
Self: Sized,
{
match self.project() {
EitherIoProj::A(val) => val.poll_write_buf(cx, buf),
EitherIoProj::B(val) => val.poll_write_buf(cx, buf),
}
}
} }

View File

@ -3,11 +3,11 @@ use std::marker::PhantomData;
use std::time::Duration; use std::time::Duration;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_connect::{ use actix_rt::net::TcpStream;
use actix_service::{apply_fn, Service, ServiceExt};
use actix_tls::connect::{
default_connector, Connect as TcpConnect, Connection as TcpConnection, default_connector, Connect as TcpConnect, Connection as TcpConnection,
}; };
use actix_rt::net::TcpStream;
use actix_service::{apply_fn, Service};
use actix_utils::timeout::{TimeoutError, TimeoutService}; use actix_utils::timeout::{TimeoutError, TimeoutService};
use http::Uri; use http::Uri;
@ -18,10 +18,10 @@ use super::pool::{ConnectionPool, Protocol};
use super::Connect; use super::Connect;
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
use actix_connect::ssl::openssl::SslConnector as OpensslConnector; use actix_tls::connect::ssl::openssl::SslConnector as OpensslConnector;
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
use actix_connect::ssl::rustls::ClientConfig; use actix_tls::connect::ssl::rustls::ClientConfig;
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
use std::sync::Arc; use std::sync::Arc;
@ -62,9 +62,9 @@ impl Connector<(), ()> {
#[allow(clippy::new_ret_no_self, clippy::let_unit_value)] #[allow(clippy::new_ret_no_self, clippy::let_unit_value)]
pub fn new() -> Connector< pub fn new() -> Connector<
impl Service< impl Service<
Request = TcpConnect<Uri>, TcpConnect<Uri>,
Response = TcpConnection<Uri, TcpStream>, Response = TcpConnection<Uri, TcpStream>,
Error = actix_connect::ConnectError, Error = actix_tls::connect::ConnectError,
> + Clone, > + Clone,
TcpStream, TcpStream,
> { > {
@ -79,7 +79,7 @@ impl Connector<(), ()> {
// Build Ssl connector with openssl, based on supplied alpn protocols // Build Ssl connector with openssl, based on supplied alpn protocols
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
fn build_ssl(protocols: Vec<Vec<u8>>) -> SslConnector { fn build_ssl(protocols: Vec<Vec<u8>>) -> SslConnector {
use actix_connect::ssl::openssl::SslMethod; use actix_tls::connect::ssl::openssl::SslMethod;
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
let mut alpn = BytesMut::with_capacity(20); let mut alpn = BytesMut::with_capacity(20);
@ -102,7 +102,7 @@ impl Connector<(), ()> {
config.set_protocols(&protocols); config.set_protocols(&protocols);
config config
.root_store .root_store
.add_server_trust_anchors(&actix_tls::rustls::TLS_SERVER_ROOTS); .add_server_trust_anchors(&actix_tls::accept::rustls::TLS_SERVER_ROOTS);
SslConnector::Rustls(Arc::new(config)) SslConnector::Rustls(Arc::new(config))
} }
@ -117,9 +117,9 @@ impl<T, U> Connector<T, U> {
where where
U1: AsyncRead + AsyncWrite + Unpin + fmt::Debug, U1: AsyncRead + AsyncWrite + Unpin + fmt::Debug,
T1: Service< T1: Service<
Request = TcpConnect<Uri>, TcpConnect<Uri>,
Response = TcpConnection<Uri, U1>, Response = TcpConnection<Uri, U1>,
Error = actix_connect::ConnectError, Error = actix_tls::connect::ConnectError,
> + Clone, > + Clone,
{ {
Connector { Connector {
@ -135,9 +135,9 @@ impl<T, U> Connector<T, U>
where where
U: AsyncRead + AsyncWrite + Unpin + fmt::Debug + 'static, U: AsyncRead + AsyncWrite + Unpin + fmt::Debug + 'static,
T: Service< T: Service<
Request = TcpConnect<Uri>, TcpConnect<Uri>,
Response = TcpConnection<Uri, U>, Response = TcpConnection<Uri, U>,
Error = actix_connect::ConnectError, Error = actix_tls::connect::ConnectError,
> + Clone > + Clone
+ 'static, + 'static,
{ {
@ -241,8 +241,8 @@ where
/// its combinator chain. /// its combinator chain.
pub fn finish( pub fn finish(
self, self,
) -> impl Service<Request = Connect, Response = impl Connection, Error = ConnectError> ) -> impl Service<Connect, Response = impl Connection, Error = ConnectError> + Clone
+ Clone { {
#[cfg(not(any(feature = "openssl", feature = "rustls")))] #[cfg(not(any(feature = "openssl", feature = "rustls")))]
{ {
let connector = TimeoutService::new( let connector = TimeoutService::new(
@ -268,11 +268,11 @@ where
#[cfg(any(feature = "openssl", feature = "rustls"))] #[cfg(any(feature = "openssl", feature = "rustls"))]
{ {
const H2: &[u8] = b"h2"; const H2: &[u8] = b"h2";
#[cfg(feature = "openssl")]
use actix_connect::ssl::openssl::OpensslConnector;
#[cfg(feature = "rustls")]
use actix_connect::ssl::rustls::{RustlsConnector, Session};
use actix_service::{boxed::service, pipeline}; use actix_service::{boxed::service, pipeline};
#[cfg(feature = "openssl")]
use actix_tls::connect::ssl::openssl::OpensslConnector;
#[cfg(feature = "rustls")]
use actix_tls::connect::ssl::rustls::{RustlsConnector, Session};
let ssl_service = TimeoutService::new( let ssl_service = TimeoutService::new(
self.config.timeout, self.config.timeout,
@ -363,8 +363,7 @@ mod connect_impl {
pub(crate) struct InnerConnector<T, Io> pub(crate) struct InnerConnector<T, Io>
where where
Io: AsyncRead + AsyncWrite + Unpin + 'static, Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io, Protocol), Error = ConnectError> + 'static,
+ 'static,
{ {
pub(crate) tcp_pool: ConnectionPool<T, Io>, pub(crate) tcp_pool: ConnectionPool<T, Io>,
} }
@ -372,8 +371,7 @@ mod connect_impl {
impl<T, Io> Clone for InnerConnector<T, Io> impl<T, Io> Clone for InnerConnector<T, Io>
where where
Io: AsyncRead + AsyncWrite + Unpin + 'static, Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io, Protocol), Error = ConnectError> + 'static,
+ 'static,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
InnerConnector { InnerConnector {
@ -382,17 +380,15 @@ mod connect_impl {
} }
} }
impl<T, Io> Service for InnerConnector<T, Io> impl<T, Io> Service<Connect> for InnerConnector<T, Io>
where where
Io: AsyncRead + AsyncWrite + Unpin + 'static, Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io, Protocol), Error = ConnectError> + 'static,
+ 'static,
{ {
type Request = Connect;
type Response = IoConnection<Io>; type Response = IoConnection<Io>;
type Error = ConnectError; type Error = ConnectError;
type Future = Either< type Future = Either<
<ConnectionPool<T, Io> as Service>::Future, <ConnectionPool<T, Io> as Service<Connect>>::Future,
Ready<Result<IoConnection<Io>, ConnectError>>, Ready<Result<IoConnection<Io>, ConnectError>>,
>; >;
@ -428,8 +424,8 @@ mod connect_impl {
where where
Io1: AsyncRead + AsyncWrite + Unpin + 'static, Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static, Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T1: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError>, T1: Service<Connect, Response = (Io1, Protocol), Error = ConnectError>,
T2: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>, T2: Service<Connect, Response = (Io2, Protocol), Error = ConnectError>,
{ {
pub(crate) tcp_pool: ConnectionPool<T1, Io1>, pub(crate) tcp_pool: ConnectionPool<T1, Io1>,
pub(crate) ssl_pool: ConnectionPool<T2, Io2>, pub(crate) ssl_pool: ConnectionPool<T2, Io2>,
@ -439,10 +435,8 @@ mod connect_impl {
where where
Io1: AsyncRead + AsyncWrite + Unpin + 'static, Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static, Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T1: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError> T1: Service<Connect, Response = (Io1, Protocol), Error = ConnectError> + 'static,
+ 'static, T2: Service<Connect, Response = (Io2, Protocol), Error = ConnectError> + 'static,
T2: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>
+ 'static,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
InnerConnector { InnerConnector {
@ -452,16 +446,13 @@ mod connect_impl {
} }
} }
impl<T1, T2, Io1, Io2> Service for InnerConnector<T1, T2, Io1, Io2> impl<T1, T2, Io1, Io2> Service<Connect> for InnerConnector<T1, T2, Io1, Io2>
where where
Io1: AsyncRead + AsyncWrite + Unpin + 'static, Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static, Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T1: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError> T1: Service<Connect, Response = (Io1, Protocol), Error = ConnectError> + 'static,
+ 'static, T2: Service<Connect, Response = (Io2, Protocol), Error = ConnectError> + 'static,
T2: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError>
+ 'static,
{ {
type Request = Connect;
type Response = EitherConnection<Io1, Io2>; type Response = EitherConnection<Io1, Io2>;
type Error = ConnectError; type Error = ConnectError;
type Future = Either< type Future = Either<
@ -491,18 +482,16 @@ mod connect_impl {
pub(crate) struct InnerConnectorResponseA<T, Io1, Io2> pub(crate) struct InnerConnectorResponseA<T, Io1, Io2>
where where
Io1: AsyncRead + AsyncWrite + Unpin + 'static, Io1: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io1, Protocol), Error = ConnectError> + 'static,
+ 'static,
{ {
#[pin] #[pin]
fut: <ConnectionPool<T, Io1> as Service>::Future, fut: <ConnectionPool<T, Io1> as Service<Connect>>::Future,
_t: PhantomData<Io2>, _t: PhantomData<Io2>,
} }
impl<T, Io1, Io2> Future for InnerConnectorResponseA<T, Io1, Io2> impl<T, Io1, Io2> Future for InnerConnectorResponseA<T, Io1, Io2>
where where
T: Service<Request = Connect, Response = (Io1, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io1, Protocol), Error = ConnectError> + 'static,
+ 'static,
Io1: AsyncRead + AsyncWrite + Unpin + 'static, Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static, Io2: AsyncRead + AsyncWrite + Unpin + 'static,
{ {
@ -520,18 +509,16 @@ mod connect_impl {
pub(crate) struct InnerConnectorResponseB<T, Io1, Io2> pub(crate) struct InnerConnectorResponseB<T, Io1, Io2>
where where
Io2: AsyncRead + AsyncWrite + Unpin + 'static, Io2: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io2, Protocol), Error = ConnectError> + 'static,
+ 'static,
{ {
#[pin] #[pin]
fut: <ConnectionPool<T, Io2> as Service>::Future, fut: <ConnectionPool<T, Io2> as Service<Connect>>::Future,
_t: PhantomData<Io1>, _t: PhantomData<Io1>,
} }
impl<T, Io1, Io2> Future for InnerConnectorResponseB<T, Io1, Io2> impl<T, Io1, Io2> Future for InnerConnectorResponseB<T, Io1, Io2>
where where
T: Service<Request = Connect, Response = (Io2, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io2, Protocol), Error = ConnectError> + 'static,
+ 'static,
Io1: AsyncRead + AsyncWrite + Unpin + 'static, Io1: AsyncRead + AsyncWrite + Unpin + 'static,
Io2: AsyncRead + AsyncWrite + Unpin + 'static, Io2: AsyncRead + AsyncWrite + Unpin + 'static,
{ {

View File

@ -1,10 +1,10 @@
use std::io; use std::io;
use actix_connect::resolver::ResolveError; use actix_tls::connect::resolver::ResolveError;
use derive_more::{Display, From}; use derive_more::{Display, From};
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
use actix_connect::ssl::openssl::{HandshakeError, SslError}; use actix_tls::accept::openssl::SslError;
use crate::error::{Error, ParseError, ResponseError}; use crate::error::{Error, ParseError, ResponseError};
use crate::http::{Error as HttpError, StatusCode}; use crate::http::{Error as HttpError, StatusCode};
@ -21,11 +21,6 @@ pub enum ConnectError {
#[display(fmt = "{}", _0)] #[display(fmt = "{}", _0)]
SslError(SslError), SslError(SslError),
/// SSL Handshake error
#[cfg(feature = "openssl")]
#[display(fmt = "{}", _0)]
SslHandshakeError(String),
/// Failed to resolve the hostname /// Failed to resolve the hostname
#[display(fmt = "Failed resolving hostname: {}", _0)] #[display(fmt = "Failed resolving hostname: {}", _0)]
Resolver(ResolveError), Resolver(ResolveError),
@ -57,25 +52,18 @@ pub enum ConnectError {
impl std::error::Error for ConnectError {} impl std::error::Error for ConnectError {}
impl From<actix_connect::ConnectError> for ConnectError { impl From<actix_tls::connect::ConnectError> for ConnectError {
fn from(err: actix_connect::ConnectError) -> ConnectError { fn from(err: actix_tls::connect::ConnectError) -> ConnectError {
match err { match err {
actix_connect::ConnectError::Resolver(e) => ConnectError::Resolver(e), actix_tls::connect::ConnectError::Resolver(e) => ConnectError::Resolver(e),
actix_connect::ConnectError::NoRecords => ConnectError::NoRecords, actix_tls::connect::ConnectError::NoRecords => ConnectError::NoRecords,
actix_connect::ConnectError::InvalidInput => panic!(), actix_tls::connect::ConnectError::InvalidInput => panic!(),
actix_connect::ConnectError::Unresolved => ConnectError::Unresolved, actix_tls::connect::ConnectError::Unresolved => ConnectError::Unresolved,
actix_connect::ConnectError::Io(e) => ConnectError::Io(e), actix_tls::connect::ConnectError::Io(e) => ConnectError::Io(e),
} }
} }
} }
#[cfg(feature = "openssl")]
impl<T: std::fmt::Debug> From<HandshakeError<T>> for ConnectError {
fn from(err: HandshakeError<T>) -> ConnectError {
ConnectError::SslHandshakeError(format!("{:?}", err))
}
}
#[derive(Debug, Display, From)] #[derive(Debug, Display, From)]
pub enum InvalidUrl { pub enum InvalidUrl {
#[display(fmt = "Missing url scheme")] #[display(fmt = "Missing url scheme")]

View File

@ -1,10 +1,10 @@
use std::io::Write; use std::io::Write;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::{io, mem, time}; use std::{io, time};
use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_codec::{AsyncRead, AsyncWrite, Framed, ReadBuf};
use bytes::buf::BufMutExt; use bytes::buf::BufMut;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures_core::Stream; use futures_core::Stream;
use futures_util::future::poll_fn; use futures_util::future::poll_fn;
@ -204,18 +204,11 @@ where
} }
impl<T: AsyncRead + AsyncWrite + Unpin + 'static> AsyncRead for H1Connection<T> { impl<T: AsyncRead + AsyncWrite + Unpin + 'static> AsyncRead for H1Connection<T> {
unsafe fn prepare_uninitialized_buffer(
&self,
buf: &mut [mem::MaybeUninit<u8>],
) -> bool {
self.io.as_ref().unwrap().prepare_uninitialized_buffer(buf)
}
fn poll_read( fn poll_read(
mut self: Pin<&mut Self>, mut self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,
buf: &mut [u8], buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<usize>> { ) -> Poll<io::Result<()>> {
Pin::new(&mut self.io.as_mut().unwrap()).poll_read(cx, buf) Pin::new(&mut self.io.as_mut().unwrap()).poll_read(cx, buf)
} }
} }

View File

@ -6,8 +6,8 @@ use std::rc::Rc;
use std::task::{Context, Poll}; 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, ReadBuf};
use actix_rt::time::{delay_for, Delay}; use actix_rt::time::{sleep, Sleep};
use actix_service::Service; use actix_service::Service;
use actix_utils::task::LocalWaker; use actix_utils::task::LocalWaker;
use bytes::Bytes; use bytes::Bytes;
@ -50,8 +50,7 @@ pub(crate) struct ConnectionPool<T, Io: 'static>(Rc<RefCell<T>>, Rc<RefCell<Inne
impl<T, Io> ConnectionPool<T, Io> impl<T, Io> ConnectionPool<T, Io>
where where
Io: AsyncRead + AsyncWrite + Unpin + 'static, Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io, Protocol), Error = ConnectError> + 'static,
+ 'static,
{ {
pub(crate) fn new(connector: T, config: ConnectorConfig) -> Self { pub(crate) fn new(connector: T, config: ConnectorConfig) -> Self {
let connector_rc = Rc::new(RefCell::new(connector)); let connector_rc = Rc::new(RefCell::new(connector));
@ -90,13 +89,11 @@ impl<T, Io> Drop for ConnectionPool<T, Io> {
} }
} }
impl<T, Io> Service for ConnectionPool<T, Io> impl<T, Io> Service<Connect> for ConnectionPool<T, Io>
where where
Io: AsyncRead + AsyncWrite + Unpin + 'static, Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError> T: Service<Connect, Response = (Io, Protocol), Error = ConnectError> + 'static,
+ 'static,
{ {
type Request = Connect;
type Response = IoConnection<Io>; type Response = IoConnection<Io>;
type Error = ConnectError; type Error = ConnectError;
type Future = LocalBoxFuture<'static, Result<IoConnection<Io>, ConnectError>>; type Future = LocalBoxFuture<'static, Result<IoConnection<Io>, ConnectError>>;
@ -334,10 +331,11 @@ where
} else { } else {
let mut io = conn.io; let mut io = conn.io;
let mut buf = [0; 2]; let mut buf = [0; 2];
let mut read_buf = ReadBuf::new(&mut buf);
if let ConnectionType::H1(ref mut s) = io { if let ConnectionType::H1(ref mut s) = io {
match Pin::new(s).poll_read(cx, &mut buf) { match Pin::new(s).poll_read(cx, &mut read_buf) {
Poll::Pending => (), Poll::Pending => (),
Poll::Ready(Ok(n)) if n > 0 => { Poll::Ready(Ok(())) if !read_buf.filled().is_empty() => {
if let Some(timeout) = self.config.disconnect_timeout { if let Some(timeout) = self.config.disconnect_timeout {
if let ConnectionType::H1(io) = io { if let ConnectionType::H1(io) = io {
actix_rt::spawn(CloseConnection::new( actix_rt::spawn(CloseConnection::new(
@ -387,9 +385,11 @@ where
} }
} }
#[pin_project::pin_project]
struct CloseConnection<T> { struct CloseConnection<T> {
io: T, io: T,
timeout: Delay, #[pin]
timeout: Sleep,
} }
impl<T> CloseConnection<T> impl<T> CloseConnection<T>
@ -399,7 +399,7 @@ where
fn new(io: T, timeout: Duration) -> Self { fn new(io: T, timeout: Duration) -> Self {
CloseConnection { CloseConnection {
io, io,
timeout: delay_for(timeout), timeout: sleep(timeout),
} }
} }
} }
@ -411,11 +411,11 @@ where
type Output = (); type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
let this = self.get_mut(); let this = self.project();
match Pin::new(&mut this.timeout).poll(cx) { match this.timeout.poll(cx) {
Poll::Ready(_) => Poll::Ready(()), Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => match Pin::new(&mut this.io).poll_shutdown(cx) { Poll::Pending => match Pin::new(this.io).poll_shutdown(cx) {
Poll::Ready(_) => Poll::Ready(()), Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => Poll::Pending, Poll::Pending => Poll::Pending,
}, },
@ -435,7 +435,7 @@ where
impl<T, Io> Future for ConnectorPoolSupport<T, Io> impl<T, Io> Future for ConnectorPoolSupport<T, Io>
where where
Io: AsyncRead + AsyncWrite + Unpin + 'static, Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Request = Connect, Response = (Io, Protocol), Error = ConnectError>, T: Service<Connect, Response = (Io, Protocol), Error = ConnectError>,
T::Future: 'static, T::Future: 'static,
{ {
type Output = (); type Output = ();

View File

@ -10,22 +10,21 @@ use actix_service::Service;
/// CloneableService might panic with some creative use of thread local storage. /// CloneableService might panic with some creative use of thread local storage.
/// See https://github.com/actix/actix-web/issues/1295 for example /// See https://github.com/actix/actix-web/issues/1295 for example
#[doc(hidden)] #[doc(hidden)]
pub(crate) struct CloneableService<T: Service>(Rc<RefCell<T>>); pub(crate) struct CloneableService<T>(Rc<RefCell<T>>);
impl<T: Service> CloneableService<T> { impl<T> CloneableService<T> {
pub(crate) fn new(service: T) -> Self { pub(crate) fn new(service: T) -> Self {
Self(Rc::new(RefCell::new(service))) Self(Rc::new(RefCell::new(service)))
} }
} }
impl<T: Service> Clone for CloneableService<T> { impl<T> Clone for CloneableService<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self(self.0.clone()) Self(self.0.clone())
} }
} }
impl<T: Service> Service for CloneableService<T> { impl<T: Service<Req>, Req> Service<Req> for CloneableService<T> {
type Request = T::Request;
type Response = T::Response; type Response = T::Response;
type Error = T::Error; type Error = T::Error;
type Future = T::Future; type Future = T::Future;
@ -34,7 +33,7 @@ impl<T: Service> Service for CloneableService<T> {
self.0.borrow_mut().poll_ready(cx) self.0.borrow_mut().poll_ready(cx)
} }
fn call(&mut self, req: T::Request) -> Self::Future { fn call(&mut self, req: Req) -> Self::Future {
self.0.borrow_mut().call(req) self.0.borrow_mut().call(req)
} }
} }

View File

@ -4,7 +4,7 @@ use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use std::{fmt, net}; use std::{fmt, net};
use actix_rt::time::{delay_for, delay_until, Delay, Instant}; use actix_rt::time::{sleep, sleep_until, Instant, Sleep};
use bytes::BytesMut; use bytes::BytesMut;
use futures_util::{future, FutureExt}; use futures_util::{future, FutureExt};
use time::OffsetDateTime; use time::OffsetDateTime;
@ -121,10 +121,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<Sleep> {
let delay_time = self.0.client_timeout; let delay_time = self.0.client_timeout;
if delay_time != 0 { if delay_time != 0 {
Some(delay_until( Some(sleep_until(
self.0.timer.now() + Duration::from_millis(delay_time), self.0.timer.now() + Duration::from_millis(delay_time),
)) ))
} else { } else {
@ -154,9 +154,9 @@ impl ServiceConfig {
#[inline] #[inline]
/// 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<Sleep> {
if let Some(ka) = self.0.keep_alive { if let Some(ka) = self.0.keep_alive {
Some(delay_until(self.0.timer.now() + ka)) Some(sleep_until(self.0.timer.now() + ka))
} else { } else {
None None
} }
@ -266,7 +266,7 @@ impl DateService {
// periodic date update // periodic date update
let s = self.clone(); let s = self.clone();
actix_rt::spawn(delay_for(Duration::from_millis(500)).then(move |_| { actix_rt::spawn(sleep(Duration::from_millis(500)).then(move |_| {
s.0.reset(); s.0.reset();
future::ready(()) future::ready(())
})); }));

View File

@ -178,11 +178,7 @@ impl ResponseError for FormError {}
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
/// `InternalServerError` for `openssl::ssl::Error` /// `InternalServerError` for `openssl::ssl::Error`
impl ResponseError for actix_connect::ssl::openssl::SslError {} impl ResponseError for actix_tls::accept::openssl::SslError {}
#[cfg(feature = "openssl")]
/// `InternalServerError` for `openssl::ssl::HandshakeError`
impl<T: std::fmt::Debug> ResponseError for actix_tls::openssl::HandshakeError<T> {}
/// Return `BAD_REQUEST` for `de::value::Error` /// Return `BAD_REQUEST` for `de::value::Error`
impl ResponseError for DeError { impl ResponseError for DeError {
@ -956,11 +952,6 @@ where
/// This is supported on feature=`actors` only /// This is supported on feature=`actors` only
impl ResponseError for actix::MailboxError {} impl ResponseError for actix::MailboxError {}
#[cfg(feature = "actors")]
/// `InternalServerError` for `actix::ResolverError`
/// This is supported on feature=`actors` only
impl ResponseError for actix::actors::resolver::ResolverError {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -8,7 +8,7 @@ use std::{
}; };
use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts}; use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts};
use actix_rt::time::{delay_until, Delay, Instant}; use actix_rt::time::{sleep_until, Instant, Sleep};
use actix_service::Service; use actix_service::Service;
use bitflags::bitflags; use bitflags::bitflags;
use bytes::{Buf, BytesMut}; use bytes::{Buf, BytesMut};
@ -51,12 +51,12 @@ bitflags! {
/// Dispatcher for HTTP/1.1 protocol /// Dispatcher for HTTP/1.1 protocol
pub struct Dispatcher<T, S, B, X, U> pub struct Dispatcher<T, S, B, X, U>
where where
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
#[pin] #[pin]
@ -69,12 +69,12 @@ where
#[pin_project(project = DispatcherStateProj)] #[pin_project(project = DispatcherStateProj)]
enum DispatcherState<T, S, B, X, U> enum DispatcherState<T, S, B, X, U>
where where
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
Normal(#[pin] InnerDispatcher<T, S, B, X, U>), Normal(#[pin] InnerDispatcher<T, S, B, X, U>),
@ -84,12 +84,12 @@ where
#[pin_project(project = InnerDispatcherProj)] #[pin_project(project = InnerDispatcherProj)]
struct InnerDispatcher<T, S, B, X, U> struct InnerDispatcher<T, S, B, X, U>
where where
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
service: CloneableService<S>, service: CloneableService<S>,
@ -106,7 +106,8 @@ where
messages: VecDeque<DispatcherMessage>, messages: VecDeque<DispatcherMessage>,
ka_expire: Instant, ka_expire: Instant,
ka_timer: Option<Delay>, #[pin]
ka_timer: Option<Sleep>,
io: Option<T>, io: Option<T>,
read_buf: BytesMut, read_buf: BytesMut,
@ -123,8 +124,8 @@ enum DispatcherMessage {
#[pin_project(project = StateProj)] #[pin_project(project = StateProj)]
enum State<S, B, X> enum State<S, B, X>
where where
S: Service<Request = Request>, S: Service<Request>,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
B: MessageBody, B: MessageBody,
{ {
None, None,
@ -135,8 +136,8 @@ where
impl<S, B, X> State<S, B, X> impl<S, B, X> State<S, B, X>
where where
S: Service<Request = Request>, S: Service<Request>,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
B: MessageBody, B: MessageBody,
{ {
fn is_empty(&self) -> bool { fn is_empty(&self) -> bool {
@ -166,13 +167,13 @@ impl PartialEq for PollResponse {
impl<T, S, B, X, U> Dispatcher<T, S, B, X, U> impl<T, S, B, X, U> Dispatcher<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
S::Response: Into<Response<B>>, S::Response: Into<Response<B>>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
/// Create HTTP/1 dispatcher. /// Create HTTP/1 dispatcher.
@ -205,7 +206,7 @@ where
codec: Codec, codec: Codec,
config: ServiceConfig, config: ServiceConfig,
read_buf: BytesMut, read_buf: BytesMut,
timeout: Option<Delay>, timeout: Option<Sleep>,
service: CloneableService<S>, service: CloneableService<S>,
expect: CloneableService<X>, expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>, upgrade: Option<CloneableService<U>>,
@ -257,13 +258,13 @@ where
impl<T, S, B, X, U> InnerDispatcher<T, S, B, X, U> impl<T, S, B, X, U> InnerDispatcher<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
S::Response: Into<Response<B>>, S::Response: Into<Response<B>>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
fn can_read(&self, cx: &mut Context<'_>) -> bool { fn can_read(&self, cx: &mut Context<'_>) -> bool {
@ -660,7 +661,7 @@ where
// shutdown timeout // shutdown timeout
if this.flags.contains(Flags::SHUTDOWN) { if this.flags.contains(Flags::SHUTDOWN) {
if let Some(interval) = this.codec.config().client_disconnect_timer() { if let Some(interval) = this.codec.config().client_disconnect_timer() {
*this.ka_timer = Some(delay_until(interval)); this.ka_timer.set(Some(sleep_until(interval)));
} else { } else {
this.flags.insert(Flags::READ_DISCONNECT); this.flags.insert(Flags::READ_DISCONNECT);
if let Some(mut payload) = this.payload.take() { if let Some(mut payload) = this.payload.take() {
@ -673,12 +674,14 @@ where
} }
} }
match Pin::new(&mut this.ka_timer.as_mut().unwrap()).poll(cx) { match this.ka_timer.as_mut().as_pin_mut().unwrap().poll(cx) {
Poll::Ready(()) => { Poll::Ready(()) => {
// if we get timeout during shutdown, drop connection // if we get timeout during shutdown, drop connection
if this.flags.contains(Flags::SHUTDOWN) { if this.flags.contains(Flags::SHUTDOWN) {
return Err(DispatchError::DisconnectTimeout); return Err(DispatchError::DisconnectTimeout);
} else if this.ka_timer.as_mut().unwrap().deadline() >= *this.ka_expire { } else if this.ka_timer.as_mut().as_pin_mut().unwrap().deadline()
>= *this.ka_expire
{
// check for any outstanding tasks // check for any outstanding tasks
if this.state.is_empty() && this.write_buf.is_empty() { if this.state.is_empty() && this.write_buf.is_empty() {
if this.flags.contains(Flags::STARTED) { if this.flags.contains(Flags::STARTED) {
@ -689,9 +692,15 @@ where
if let Some(deadline) = if let Some(deadline) =
this.codec.config().client_disconnect_timer() this.codec.config().client_disconnect_timer()
{ {
if let Some(mut timer) = this.ka_timer.as_mut() { if let Some(timer) = this.ka_timer.as_mut().as_pin_mut()
{
timer.reset(deadline); timer.reset(deadline);
let _ = Pin::new(&mut timer).poll(cx); let _ = this
.ka_timer
.as_mut()
.as_pin_mut()
.unwrap()
.poll(cx);
} }
} else { } else {
// no shutdown timeout, drop socket // no shutdown timeout, drop socket
@ -716,14 +725,15 @@ where
} else if let Some(deadline) = } else if let Some(deadline) =
this.codec.config().keep_alive_expire() this.codec.config().keep_alive_expire()
{ {
if let Some(mut timer) = this.ka_timer.as_mut() { if let Some(timer) = this.ka_timer.as_mut().as_pin_mut() {
timer.reset(deadline); timer.reset(deadline);
let _ = Pin::new(&mut timer).poll(cx); let _ =
this.ka_timer.as_mut().as_pin_mut().unwrap().poll(cx);
} }
} }
} else if let Some(mut timer) = this.ka_timer.as_mut() { } else if let Some(timer) = this.ka_timer.as_mut().as_pin_mut() {
timer.reset(*this.ka_expire); timer.reset(*this.ka_expire);
let _ = Pin::new(&mut timer).poll(cx); let _ = this.ka_timer.as_mut().as_pin_mut().unwrap().poll(cx);
} }
} }
Poll::Pending => (), Poll::Pending => (),
@ -736,13 +746,13 @@ where
impl<T, S, B, X, U> Future for Dispatcher<T, S, B, X, U> impl<T, S, B, X, U> Future for Dispatcher<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
S::Response: Into<Response<B>>, S::Response: Into<Response<B>>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
type Output = Result<(), DispatchError>; type Output = Result<(), DispatchError>;
@ -951,12 +961,12 @@ fn read<T>(
where where
T: AsyncRead + Unpin, T: AsyncRead + Unpin,
{ {
Pin::new(io).poll_read_buf(cx, buf) actix_codec::poll_read_buf(Pin::new(io), cx, buf)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{marker::PhantomData, str}; use std::str;
use actix_service::fn_service; use actix_service::fn_service;
use futures_util::future::{lazy, ready}; use futures_util::future::{lazy, ready};
@ -985,21 +995,19 @@ mod tests {
} }
} }
fn ok_service() -> impl Service<Request = Request, Response = Response, Error = Error> fn ok_service() -> impl Service<Request, Response = Response, Error = Error> {
{
fn_service(|_req: Request| ready(Ok::<_, Error>(Response::Ok().finish()))) fn_service(|_req: Request| ready(Ok::<_, Error>(Response::Ok().finish())))
} }
fn echo_path_service( fn echo_path_service() -> impl Service<Request, Response = Response, Error = Error> {
) -> impl Service<Request = Request, Response = Response, Error = Error> {
fn_service(|req: Request| { fn_service(|req: Request| {
let path = req.path().as_bytes(); let path = req.path().as_bytes();
ready(Ok::<_, Error>(Response::Ok().body(Body::from_slice(path)))) ready(Ok::<_, Error>(Response::Ok().body(Body::from_slice(path))))
}) })
} }
fn echo_payload_service( fn echo_payload_service() -> impl Service<Request, Response = Response, Error = Error>
) -> impl Service<Request = Request, Response = Response, Error = Error> { {
fn_service(|mut req: Request| { fn_service(|mut req: Request| {
Box::pin(async move { Box::pin(async move {
use futures_util::stream::StreamExt as _; use futures_util::stream::StreamExt as _;
@ -1007,7 +1015,7 @@ mod tests {
let mut pl = req.take_payload(); let mut pl = req.take_payload();
let mut body = BytesMut::new(); let mut body = BytesMut::new();
while let Some(chunk) = pl.next().await { while let Some(chunk) = pl.next().await {
body.extend_from_slice(chunk.unwrap().bytes()) body.extend_from_slice(chunk.unwrap().chunk())
} }
Ok::<_, Error>(Response::Ok().body(body)) Ok::<_, Error>(Response::Ok().body(body))
@ -1020,7 +1028,7 @@ mod tests {
lazy(|cx| { lazy(|cx| {
let buf = TestBuffer::new("GET /test HTTP/1\r\n\r\n"); let buf = TestBuffer::new("GET /test HTTP/1\r\n\r\n");
let h1 = Dispatcher::<_, _, _, _, UpgradeHandler<TestBuffer>>::new( let h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new(
buf, buf,
ServiceConfig::default(), ServiceConfig::default(),
CloneableService::new(ok_service()), CloneableService::new(ok_service()),
@ -1060,7 +1068,7 @@ mod tests {
let cfg = ServiceConfig::new(KeepAlive::Disabled, 1, 1, false, None); let cfg = ServiceConfig::new(KeepAlive::Disabled, 1, 1, false, None);
let h1 = Dispatcher::<_, _, _, _, UpgradeHandler<TestBuffer>>::new( let h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new(
buf, buf,
cfg, cfg,
CloneableService::new(echo_path_service()), CloneableService::new(echo_path_service()),
@ -1114,7 +1122,7 @@ mod tests {
let cfg = ServiceConfig::new(KeepAlive::Disabled, 1, 1, false, None); let cfg = ServiceConfig::new(KeepAlive::Disabled, 1, 1, false, None);
let h1 = Dispatcher::<_, _, _, _, UpgradeHandler<TestBuffer>>::new( let h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new(
buf, buf,
cfg, cfg,
CloneableService::new(echo_path_service()), CloneableService::new(echo_path_service()),
@ -1163,7 +1171,7 @@ mod tests {
lazy(|cx| { lazy(|cx| {
let mut buf = TestSeqBuffer::empty(); let mut buf = TestSeqBuffer::empty();
let cfg = ServiceConfig::new(KeepAlive::Disabled, 0, 0, false, None); let cfg = ServiceConfig::new(KeepAlive::Disabled, 0, 0, false, None);
let h1 = Dispatcher::<_, _, _, _, UpgradeHandler<_>>::new( let h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new(
buf.clone(), buf.clone(),
cfg, cfg,
CloneableService::new(echo_payload_service()), CloneableService::new(echo_payload_service()),
@ -1234,7 +1242,7 @@ mod tests {
lazy(|cx| { lazy(|cx| {
let mut buf = TestSeqBuffer::empty(); let mut buf = TestSeqBuffer::empty();
let cfg = ServiceConfig::new(KeepAlive::Disabled, 0, 0, false, None); let cfg = ServiceConfig::new(KeepAlive::Disabled, 0, 0, false, None);
let h1 = Dispatcher::<_, _, _, _, UpgradeHandler<_>>::new( let h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new(
buf.clone(), buf.clone(),
cfg, cfg,
CloneableService::new(echo_path_service()), CloneableService::new(echo_path_service()),
@ -1293,12 +1301,12 @@ mod tests {
lazy(|cx| { lazy(|cx| {
let mut buf = TestSeqBuffer::empty(); let mut buf = TestSeqBuffer::empty();
let cfg = ServiceConfig::new(KeepAlive::Disabled, 0, 0, false, None); let cfg = ServiceConfig::new(KeepAlive::Disabled, 0, 0, false, None);
let h1 = Dispatcher::<_, _, _, _, UpgradeHandler<_>>::new( let h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new(
buf.clone(), buf.clone(),
cfg, cfg,
CloneableService::new(ok_service()), CloneableService::new(ok_service()),
CloneableService::new(ExpectHandler), CloneableService::new(ExpectHandler),
Some(CloneableService::new(UpgradeHandler(PhantomData))), Some(CloneableService::new(UpgradeHandler)),
Extensions::new(), Extensions::new(),
None, None,
); );

View File

@ -135,7 +135,7 @@ pub(crate) trait MessageType: Sized {
let mut has_date = false; let mut has_date = false;
let mut buf = dst.bytes_mut().as_mut_ptr() as *mut u8; let mut buf = dst.chunk_mut().as_mut_ptr() as *mut u8;
let mut remaining = dst.capacity() - dst.len(); let mut remaining = dst.capacity() - dst.len();
// tracks bytes written since last buffer resize // tracks bytes written since last buffer resize
@ -177,7 +177,7 @@ pub(crate) trait MessageType: Sized {
// re-assign buf raw pointer since it's possible that the buffer was // re-assign buf raw pointer since it's possible that the buffer was
// reallocated and/or resized // reallocated and/or resized
buf = dst.bytes_mut().as_mut_ptr() as *mut u8; buf = dst.chunk_mut().as_mut_ptr() as *mut u8;
} }
// SAFETY: on each write, it is enough to ensure that the advancement of the // SAFETY: on each write, it is enough to ensure that the advancement of the
@ -224,7 +224,7 @@ pub(crate) trait MessageType: Sized {
// re-assign buf raw pointer since it's possible that the buffer was // re-assign buf raw pointer since it's possible that the buffer was
// reallocated and/or resized // reallocated and/or resized
buf = dst.bytes_mut().as_mut_ptr() as *mut u8; buf = dst.chunk_mut().as_mut_ptr() as *mut u8;
} }
// SAFETY: on each write, it is enough to ensure that the advancement of // SAFETY: on each write, it is enough to ensure that the advancement of

View File

@ -8,11 +8,10 @@ use crate::request::Request;
pub struct ExpectHandler; pub struct ExpectHandler;
impl ServiceFactory for ExpectHandler { impl ServiceFactory<Request> for ExpectHandler {
type Config = ();
type Request = Request;
type Response = Request; type Response = Request;
type Error = Error; type Error = Error;
type Config = ();
type Service = ExpectHandler; type Service = ExpectHandler;
type InitError = Error; type InitError = Error;
type Future = Ready<Result<Self::Service, Self::InitError>>; type Future = Ready<Result<Self::Service, Self::InitError>>;
@ -22,8 +21,7 @@ impl ServiceFactory for ExpectHandler {
} }
} }
impl Service for ExpectHandler { impl Service<Request> for ExpectHandler {
type Request = Request;
type Response = Request; type Response = Request;
type Error = Error; type Error = Error;
type Future = Ready<Result<Self::Response, Self::Error>>; type Future = Ready<Result<Self::Response, Self::Error>>;

View File

@ -24,25 +24,25 @@ use super::dispatcher::Dispatcher;
use super::{ExpectHandler, UpgradeHandler}; use super::{ExpectHandler, UpgradeHandler};
/// `ServiceFactory` implementation for HTTP1 transport /// `ServiceFactory` implementation for HTTP1 transport
pub struct H1Service<T, S, B, X = ExpectHandler, U = UpgradeHandler<T>> { pub struct H1Service<T, S, B, X = ExpectHandler, U = UpgradeHandler> {
srv: S, srv: S,
cfg: ServiceConfig, cfg: ServiceConfig,
expect: X, expect: X,
upgrade: Option<U>, upgrade: Option<U>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>, on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<(T, B)>, _t: PhantomData<B>,
} }
impl<T, S, B> H1Service<T, S, B> impl<T, S, B> H1Service<T, S, B>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
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>>,
B: MessageBody, B: MessageBody,
{ {
/// Create new `HttpService` instance with config. /// Create new `HttpService` instance with config.
pub(crate) fn with_config<F: IntoServiceFactory<S>>( pub(crate) fn with_config<F: IntoServiceFactory<S, Request>>(
cfg: ServiceConfig, cfg: ServiceConfig,
service: F, service: F,
) -> Self { ) -> Self {
@ -59,19 +59,15 @@ where
impl<S, B, X, U> H1Service<TcpStream, S, B, X, U> impl<S, B, X, U> H1Service<TcpStream, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
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>>,
B: MessageBody, B: MessageBody,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
U: ServiceFactory< U: ServiceFactory<(Request, Framed<TcpStream, Codec>), Config = (), Response = ()>,
Config = (),
Request = (Request, Framed<TcpStream, Codec>),
Response = (),
>,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
{ {
@ -79,8 +75,8 @@ where
pub fn tcp( pub fn tcp(
self, self,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = DispatchError, Error = DispatchError,
InitError = (), InitError = (),
@ -97,22 +93,23 @@ where
mod openssl { mod openssl {
use super::*; use super::*;
use actix_tls::openssl::{Acceptor, SslAcceptor, SslStream}; use actix_service::ServiceFactoryExt;
use actix_tls::{openssl::HandshakeError, TlsError}; use actix_tls::accept::openssl::{Acceptor, SslAcceptor, SslError, SslStream};
use actix_tls::accept::TlsError;
impl<S, B, X, U> H1Service<SslStream<TcpStream>, S, B, X, U> impl<S, B, X, U> H1Service<SslStream<TcpStream>, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
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>>,
B: MessageBody, B: MessageBody,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
U: ServiceFactory< U: ServiceFactory<
(Request, Framed<SslStream<TcpStream>, Codec>),
Config = (), Config = (),
Request = (Request, Framed<SslStream<TcpStream>, Codec>),
Response = (), Response = (),
>, >,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
@ -123,10 +120,10 @@ mod openssl {
self, self,
acceptor: SslAcceptor, acceptor: SslAcceptor,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = TlsError<HandshakeError<TcpStream>, DispatchError>, Error = TlsError<SslError, DispatchError>,
InitError = (), InitError = (),
> { > {
pipeline_factory( pipeline_factory(
@ -146,23 +143,24 @@ mod openssl {
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
mod rustls { mod rustls {
use super::*; use super::*;
use actix_tls::rustls::{Acceptor, ServerConfig, TlsStream}; use actix_service::ServiceFactoryExt;
use actix_tls::TlsError; use actix_tls::accept::rustls::{Acceptor, ServerConfig, TlsStream};
use actix_tls::accept::TlsError;
use std::{fmt, io}; use std::{fmt, io};
impl<S, B, X, U> H1Service<TlsStream<TcpStream>, S, B, X, U> impl<S, B, X, U> H1Service<TlsStream<TcpStream>, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
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>>,
B: MessageBody, B: MessageBody,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
U: ServiceFactory< U: ServiceFactory<
(Request, Framed<TlsStream<TcpStream>, Codec>),
Config = (), Config = (),
Request = (Request, Framed<TlsStream<TcpStream>, Codec>),
Response = (), Response = (),
>, >,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
@ -173,8 +171,8 @@ mod rustls {
self, self,
config: ServerConfig, config: ServerConfig,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = TlsError<io::Error, DispatchError>, Error = TlsError<io::Error, DispatchError>,
InitError = (), InitError = (),
@ -195,7 +193,7 @@ mod rustls {
impl<T, S, B, X, U> H1Service<T, S, B, X, U> impl<T, S, B, X, U> H1Service<T, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
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,
@ -203,7 +201,7 @@ where
{ {
pub fn expect<X1>(self, expect: X1) -> H1Service<T, S, B, X1, U> pub fn expect<X1>(self, expect: X1) -> H1Service<T, S, B, X1, U>
where where
X1: ServiceFactory<Request = Request, Response = Request>, X1: ServiceFactory<Request, Response = Request>,
X1::Error: Into<Error>, X1::Error: Into<Error>,
X1::InitError: fmt::Debug, X1::InitError: fmt::Debug,
{ {
@ -219,7 +217,7 @@ where
pub fn upgrade<U1>(self, upgrade: Option<U1>) -> H1Service<T, S, B, X, U1> pub fn upgrade<U1>(self, upgrade: Option<U1>) -> H1Service<T, S, B, X, U1>
where where
U1: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>, U1: ServiceFactory<(Request, Framed<T, Codec>), Response = ()>,
U1::Error: fmt::Display, U1::Error: fmt::Display,
U1::InitError: fmt::Debug, U1::InitError: fmt::Debug,
{ {
@ -240,27 +238,27 @@ where
} }
} }
impl<T, S, B, X, U> ServiceFactory for H1Service<T, S, B, X, U> impl<T, S, B, X, U> ServiceFactory<(T, Option<net::SocketAddr>)>
for H1Service<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
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,
B: MessageBody, B: MessageBody,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
U: ServiceFactory<Config = (), Request = (Request, Framed<T, Codec>), Response = ()>, U: ServiceFactory<(Request, Framed<T, Codec>), Config = (), Response = ()>,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
{ {
type Config = ();
type Request = (T, Option<net::SocketAddr>);
type Response = (); type Response = ();
type Error = DispatchError; type Error = DispatchError;
type InitError = (); type Config = ();
type Service = H1ServiceHandler<T, S::Service, B, X::Service, U::Service>; type Service = H1ServiceHandler<T, S::Service, B, X::Service, U::Service>;
type InitError = ();
type Future = H1ServiceResponse<T, S, B, X, U>; type Future = H1ServiceResponse<T, S, B, X, U>;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {
@ -281,13 +279,13 @@ where
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct H1ServiceResponse<T, S, B, X, U> pub struct H1ServiceResponse<T, S, B, X, U>
where where
S: ServiceFactory<Request = Request>, S: ServiceFactory<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
X: ServiceFactory<Request = Request, Response = Request>, X: ServiceFactory<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
U: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>, U: ServiceFactory<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
{ {
@ -307,15 +305,15 @@ where
impl<T, S, B, X, U> Future for H1ServiceResponse<T, S, B, X, U> impl<T, S, B, X, U> Future for H1ServiceResponse<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: ServiceFactory<Request = Request>, S: ServiceFactory<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,
B: MessageBody, B: MessageBody,
X: ServiceFactory<Request = Request, Response = Request>, X: ServiceFactory<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
U: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>, U: ServiceFactory<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
{ {
@ -362,24 +360,29 @@ where
} }
/// `Service` implementation for HTTP/1 transport /// `Service` implementation for HTTP/1 transport
pub struct H1ServiceHandler<T, S: Service, B, X: Service, U: Service> { pub struct H1ServiceHandler<T, S, B, X, U>
where
S: Service<Request>,
X: Service<Request>,
U: Service<(Request, Framed<T, Codec>)>,
{
srv: CloneableService<S>, srv: CloneableService<S>,
expect: CloneableService<X>, expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>, upgrade: Option<CloneableService<U>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>, on_connect_ext: Option<Rc<ConnectCallback<T>>>,
cfg: ServiceConfig, cfg: ServiceConfig,
_t: PhantomData<(T, B)>, _t: PhantomData<B>,
} }
impl<T, S, B, X, U> H1ServiceHandler<T, S, B, X, U> impl<T, S, B, X, U> H1ServiceHandler<T, S, B, X, U>
where where
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
S::Response: Into<Response<B>>, S::Response: Into<Response<B>>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
fn new( fn new(
@ -400,19 +403,19 @@ where
} }
} }
impl<T, S, B, X, U> Service for H1ServiceHandler<T, S, B, X, U> impl<T, S, B, X, U> Service<(T, Option<net::SocketAddr>)>
for H1ServiceHandler<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
S::Response: Into<Response<B>>, S::Response: Into<Response<B>>,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
{ {
type Request = (T, Option<net::SocketAddr>);
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>;
@ -459,7 +462,7 @@ where
} }
} }
fn call(&mut self, (io, addr): Self::Request) -> Self::Future { fn call(&mut self, (io, addr): (T, Option<net::SocketAddr>)) -> Self::Future {
let mut connect_extensions = Extensions::new(); let mut connect_extensions = Extensions::new();
if let Some(ref handler) = self.on_connect_ext { if let Some(ref handler) = self.on_connect_ext {
// run on_connect_ext callback, populating connect extensions // run on_connect_ext callback, populating connect extensions

View File

@ -1,4 +1,3 @@
use std::marker::PhantomData;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_codec::Framed; use actix_codec::Framed;
@ -9,14 +8,13 @@ use crate::error::Error;
use crate::h1::Codec; use crate::h1::Codec;
use crate::request::Request; use crate::request::Request;
pub struct UpgradeHandler<T>(pub(crate) PhantomData<T>); pub struct UpgradeHandler;
impl<T> ServiceFactory for UpgradeHandler<T> { impl<T> ServiceFactory<(Request, Framed<T, Codec>)> for UpgradeHandler {
type Config = ();
type Request = (Request, Framed<T, Codec>);
type Response = (); type Response = ();
type Error = Error; type Error = Error;
type Service = UpgradeHandler<T>; type Config = ();
type Service = UpgradeHandler;
type InitError = Error; type InitError = Error;
type Future = Ready<Result<Self::Service, Self::InitError>>; type Future = Ready<Result<Self::Service, Self::InitError>>;
@ -25,8 +23,7 @@ impl<T> ServiceFactory for UpgradeHandler<T> {
} }
} }
impl<T> Service for UpgradeHandler<T> { impl<T> Service<(Request, Framed<T, Codec>)> for UpgradeHandler {
type Request = (Request, Framed<T, Codec>);
type Response = (); type Response = ();
type Error = Error; type Error = Error;
type Future = Ready<Result<Self::Response, Self::Error>>; type Future = Ready<Result<Self::Response, Self::Error>>;
@ -35,7 +32,7 @@ impl<T> Service for UpgradeHandler<T> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
fn call(&mut self, _: Self::Request) -> Self::Future { fn call(&mut self, _: (Request, Framed<T, Codec>)) -> Self::Future {
ready(Ok(())) ready(Ok(()))
} }
} }

View File

@ -6,7 +6,7 @@ use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_rt::time::{Delay, Instant}; use actix_rt::time::{Instant, Sleep};
use actix_service::Service; use actix_service::Service;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use h2::server::{Connection, SendResponse}; use h2::server::{Connection, SendResponse};
@ -29,9 +29,11 @@ const CHUNK_SIZE: usize = 16_384;
/// Dispatcher for HTTP/2 protocol /// Dispatcher for HTTP/2 protocol
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct Dispatcher<T, S: Service<Request = Request>, B: MessageBody> pub struct Dispatcher<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request>,
B: MessageBody,
{ {
service: CloneableService<S>, service: CloneableService<S>,
connection: Connection<T, Bytes>, connection: Connection<T, Bytes>,
@ -39,14 +41,14 @@ where
config: ServiceConfig, config: ServiceConfig,
peer_addr: Option<net::SocketAddr>, peer_addr: Option<net::SocketAddr>,
ka_expire: Instant, ka_expire: Instant,
ka_timer: Option<Delay>, ka_timer: Option<Sleep>,
_t: PhantomData<B>, _t: PhantomData<B>,
} }
impl<T, S, B> Dispatcher<T, S, B> impl<T, S, B> Dispatcher<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error>, S::Error: Into<Error>,
// S::Future: 'static, // S::Future: 'static,
S::Response: Into<Response<B>>, S::Response: Into<Response<B>>,
@ -57,7 +59,7 @@ where
connection: Connection<T, Bytes>, connection: Connection<T, Bytes>,
on_connect_data: Extensions, on_connect_data: Extensions,
config: ServiceConfig, config: ServiceConfig,
timeout: Option<Delay>, timeout: Option<Sleep>,
peer_addr: Option<net::SocketAddr>, peer_addr: Option<net::SocketAddr>,
) -> Self { ) -> Self {
// let keepalive = config.keep_alive_enabled(); // let keepalive = config.keep_alive_enabled();
@ -92,7 +94,7 @@ where
impl<T, S, B> Future for Dispatcher<T, S, B> impl<T, S, B> Future for Dispatcher<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,

View File

@ -36,14 +36,14 @@ pub struct H2Service<T, S, B> {
impl<T, S, B> H2Service<T, S, B> impl<T, S, B> H2Service<T, S, B>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
/// Create new `HttpService` instance with config. /// Create new `HttpService` instance with config.
pub(crate) fn with_config<F: IntoServiceFactory<S>>( pub(crate) fn with_config<F: IntoServiceFactory<S, Request>>(
cfg: ServiceConfig, cfg: ServiceConfig,
service: F, service: F,
) -> Self { ) -> Self {
@ -64,18 +64,18 @@ where
impl<S, B> H2Service<TcpStream, S, B> impl<S, B> H2Service<TcpStream, S, B>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
/// Create simple tcp based service /// Create simple tcp based service
pub fn tcp( pub fn tcp(
self, self,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = DispatchError, Error = DispatchError,
InitError = S::InitError, InitError = S::InitError,
@ -92,18 +92,18 @@ where
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
mod openssl { mod openssl {
use actix_service::{fn_factory, fn_service}; use actix_service::{fn_factory, fn_service, ServiceFactoryExt};
use actix_tls::openssl::{Acceptor, SslAcceptor, SslStream}; use actix_tls::accept::openssl::{Acceptor, SslAcceptor, SslError, SslStream};
use actix_tls::{openssl::HandshakeError, TlsError}; use actix_tls::accept::TlsError;
use super::*; use super::*;
impl<S, B> H2Service<SslStream<TcpStream>, S, B> impl<S, B> H2Service<SslStream<TcpStream>, S, B>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
/// Create ssl based service /// Create ssl based service
@ -111,10 +111,10 @@ mod openssl {
self, self,
acceptor: SslAcceptor, acceptor: SslAcceptor,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = TlsError<HandshakeError<TcpStream>, DispatchError>, Error = TlsError<SslError, DispatchError>,
InitError = S::InitError, InitError = S::InitError,
> { > {
pipeline_factory( pipeline_factory(
@ -136,16 +136,17 @@ mod openssl {
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
mod rustls { mod rustls {
use super::*; use super::*;
use actix_tls::rustls::{Acceptor, ServerConfig, TlsStream}; use actix_service::ServiceFactoryExt;
use actix_tls::TlsError; use actix_tls::accept::rustls::{Acceptor, ServerConfig, TlsStream};
use actix_tls::accept::TlsError;
use std::io; use std::io;
impl<S, B> H2Service<TlsStream<TcpStream>, S, B> impl<S, B> H2Service<TlsStream<TcpStream>, S, B>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
/// Create openssl based service /// Create openssl based service
@ -153,8 +154,8 @@ mod rustls {
self, self,
mut config: ServerConfig, mut config: ServerConfig,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = TlsError<io::Error, DispatchError>, Error = TlsError<io::Error, DispatchError>,
InitError = S::InitError, InitError = S::InitError,
@ -178,21 +179,20 @@ mod rustls {
} }
} }
impl<T, S, B> ServiceFactory for H2Service<T, S, B> impl<T, S, B> ServiceFactory<(T, Option<net::SocketAddr>)> for H2Service<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
type Config = ();
type Request = (T, Option<net::SocketAddr>);
type Response = (); type Response = ();
type Error = DispatchError; type Error = DispatchError;
type InitError = S::InitError; type Config = ();
type Service = H2ServiceHandler<T, S::Service, B>; type Service = H2ServiceHandler<T, S::Service, B>;
type InitError = S::InitError;
type Future = H2ServiceResponse<T, S, B>; type Future = H2ServiceResponse<T, S, B>;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {
@ -207,21 +207,24 @@ where
#[doc(hidden)] #[doc(hidden)]
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct H2ServiceResponse<T, S: ServiceFactory, B> { pub struct H2ServiceResponse<T, S, B>
where
S: ServiceFactory<Request>,
{
#[pin] #[pin]
fut: S::Future, fut: S::Future,
cfg: Option<ServiceConfig>, cfg: Option<ServiceConfig>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>, on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<(T, B)>, _t: PhantomData<B>,
} }
impl<T, S, B> Future for H2ServiceResponse<T, S, B> impl<T, S, B> Future for H2ServiceResponse<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
type Output = Result<H2ServiceHandler<T, S::Service, B>, S::InitError>; type Output = Result<H2ServiceHandler<T, S::Service, B>, S::InitError>;
@ -241,16 +244,19 @@ where
} }
/// `Service` implementation for http/2 transport /// `Service` implementation for http/2 transport
pub struct H2ServiceHandler<T, S: Service, B> { pub struct H2ServiceHandler<T, S, B>
where
S: Service<Request>,
{
srv: CloneableService<S>, srv: CloneableService<S>,
cfg: ServiceConfig, cfg: ServiceConfig,
on_connect_ext: Option<Rc<ConnectCallback<T>>>, on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<(T, B)>, _t: PhantomData<B>,
} }
impl<T, S, B> H2ServiceHandler<T, S, B> impl<T, S, B> H2ServiceHandler<T, S, B>
where where
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
@ -270,16 +276,15 @@ where
} }
} }
impl<T, S, B> Service for H2ServiceHandler<T, S, B> impl<T, S, B> Service<(T, Option<net::SocketAddr>)> for H2ServiceHandler<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
type Request = (T, Option<net::SocketAddr>);
type Response = (); type Response = ();
type Error = DispatchError; type Error = DispatchError;
type Future = H2ServiceHandlerResponse<T, S, B>; type Future = H2ServiceHandlerResponse<T, S, B>;
@ -292,7 +297,7 @@ where
}) })
} }
fn call(&mut self, (io, addr): Self::Request) -> Self::Future { fn call(&mut self, (io, addr): (T, Option<net::SocketAddr>)) -> Self::Future {
let mut connect_extensions = Extensions::new(); let mut connect_extensions = Extensions::new();
if let Some(ref handler) = self.on_connect_ext { if let Some(ref handler) = self.on_connect_ext {
// run on_connect_ext callback, populating connect extensions // run on_connect_ext callback, populating connect extensions
@ -311,7 +316,7 @@ where
} }
} }
enum State<T, S: Service<Request = Request>, B: MessageBody> enum State<T, S: Service<Request>, B: MessageBody>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S::Future: 'static, S::Future: 'static,
@ -329,7 +334,7 @@ where
pub struct H2ServiceHandlerResponse<T, S, B> pub struct H2ServiceHandlerResponse<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
@ -341,7 +346,7 @@ where
impl<T, S, B> Future for H2ServiceHandlerResponse<T, S, B> impl<T, S, B> Future for H2ServiceHandlerResponse<T, S, B>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,

View File

@ -3,7 +3,8 @@ use std::io::Write;
use std::str::FromStr; use std::str::FromStr;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use bytes::{buf::BufMutExt, BytesMut}; use bytes::buf::BufMut;
use bytes::BytesMut;
use http::header::{HeaderValue, InvalidHeaderValue}; use http::header::{HeaderValue, InvalidHeaderValue};
use time::{offset, OffsetDateTime, PrimitiveDateTime}; use time::{offset, OffsetDateTime, PrimitiveDateTime};

View File

@ -23,6 +23,10 @@ impl<P> HttpMessage for Request<P> {
&self.head().headers &self.head().headers
} }
fn take_payload(&mut self) -> Payload<P> {
std::mem::replace(&mut self.payload, Payload::None)
}
/// Request extensions /// Request extensions
#[inline] #[inline]
fn extensions(&self) -> Ref<'_, Extensions> { fn extensions(&self) -> Ref<'_, Extensions> {
@ -34,10 +38,6 @@ impl<P> HttpMessage for Request<P> {
fn extensions_mut(&self) -> RefMut<'_, Extensions> { fn extensions_mut(&self) -> RefMut<'_, Extensions> {
self.head.extensions_mut() self.head.extensions_mut()
} }
fn take_payload(&mut self) -> Payload<P> {
std::mem::replace(&mut self.payload, Payload::None)
}
} }
impl From<Message<RequestHead>> for Request<PayloadStream> { impl From<Message<RequestHead>> for Request<PayloadStream> {

View File

@ -22,22 +22,22 @@ use crate::response::Response;
use crate::{h1, h2::Dispatcher, ConnectCallback, Extensions, Protocol}; use crate::{h1, h2::Dispatcher, ConnectCallback, Extensions, Protocol};
/// A `ServiceFactory` for HTTP/1.1 or HTTP/2 protocol. /// A `ServiceFactory` for HTTP/1.1 or HTTP/2 protocol.
pub struct HttpService<T, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler<T>> { pub struct HttpService<T, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler> {
srv: S, srv: S,
cfg: ServiceConfig, cfg: ServiceConfig,
expect: X, expect: X,
upgrade: Option<U>, upgrade: Option<U>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>, on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<(T, B)>, _t: PhantomData<B>,
} }
impl<T, S, B> HttpService<T, S, B> impl<T, S, B> HttpService<T, S, B>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
/// Create builder for `HttpService` instance. /// Create builder for `HttpService` instance.
@ -48,15 +48,15 @@ where
impl<T, S, B> HttpService<T, S, B> impl<T, S, B> HttpService<T, S, B>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
/// Create new `HttpService` instance. /// Create new `HttpService` instance.
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self { pub fn new<F: IntoServiceFactory<S, Request>>(service: F) -> Self {
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0, false, None); let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0, false, None);
HttpService { HttpService {
@ -70,7 +70,7 @@ where
} }
/// Create new `HttpService` instance with config. /// Create new `HttpService` instance with config.
pub(crate) fn with_config<F: IntoServiceFactory<S>>( pub(crate) fn with_config<F: IntoServiceFactory<S, Request>>(
cfg: ServiceConfig, cfg: ServiceConfig,
service: F, service: F,
) -> Self { ) -> Self {
@ -87,11 +87,11 @@ where
impl<T, S, B, X, U> HttpService<T, S, B, X, U> impl<T, S, B, X, U> HttpService<T, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody, B: MessageBody,
{ {
/// Provide service for `EXPECT: 100-Continue` support. /// Provide service for `EXPECT: 100-Continue` support.
@ -101,10 +101,10 @@ where
/// request will be forwarded to main service. /// request will be forwarded to main service.
pub fn expect<X1>(self, expect: X1) -> HttpService<T, S, B, X1, U> pub fn expect<X1>(self, expect: X1) -> HttpService<T, S, B, X1, U>
where where
X1: ServiceFactory<Config = (), Request = Request, Response = Request>, X1: ServiceFactory<Request, Config = (), Response = Request>,
X1::Error: Into<Error>, X1::Error: Into<Error>,
X1::InitError: fmt::Debug, X1::InitError: fmt::Debug,
<X1::Service as Service>::Future: 'static, <X1::Service as Service<Request>>::Future: 'static,
{ {
HttpService { HttpService {
expect, expect,
@ -122,14 +122,10 @@ 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, S, B, X, U1> pub fn upgrade<U1>(self, upgrade: Option<U1>) -> HttpService<T, S, B, X, U1>
where where
U1: ServiceFactory< U1: ServiceFactory<(Request, Framed<T, h1::Codec>), Config = (), Response = ()>,
Config = (),
Request = (Request, Framed<T, h1::Codec>),
Response = (),
>,
U1::Error: fmt::Display, U1::Error: fmt::Display,
U1::InitError: fmt::Debug, U1::InitError: fmt::Debug,
<U1::Service as Service>::Future: 'static, <U1::Service as Service<(Request, Framed<T, h1::Codec>)>>::Future: 'static,
{ {
HttpService { HttpService {
upgrade, upgrade,
@ -150,31 +146,31 @@ where
impl<S, B, X, U> HttpService<TcpStream, S, B, X, U> impl<S, B, X, U> HttpService<TcpStream, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
<X::Service as Service>::Future: 'static, <X::Service as Service<Request>>::Future: 'static,
U: ServiceFactory< U: ServiceFactory<
(Request, Framed<TcpStream, h1::Codec>),
Config = (), Config = (),
Request = (Request, Framed<TcpStream, h1::Codec>),
Response = (), Response = (),
>, >,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
<U::Service as Service>::Future: 'static, <U::Service as Service<(Request, Framed<TcpStream, h1::Codec>)>>::Future: 'static,
{ {
/// Create simple tcp stream service /// Create simple tcp stream service
pub fn tcp( pub fn tcp(
self, self,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = DispatchError, Error = DispatchError,
InitError = (), InitError = (),
@ -190,39 +186,40 @@ where
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
mod openssl { mod openssl {
use super::*; use super::*;
use actix_tls::openssl::{Acceptor, SslAcceptor, SslStream}; use actix_service::ServiceFactoryExt;
use actix_tls::{openssl::HandshakeError, TlsError}; use actix_tls::accept::openssl::{Acceptor, SslAcceptor, SslError, SslStream};
use actix_tls::accept::TlsError;
impl<S, B, X, U> HttpService<SslStream<TcpStream>, S, B, X, U> impl<S, B, X, U> HttpService<SslStream<TcpStream>, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
<X::Service as Service>::Future: 'static, <X::Service as Service<Request>>::Future: 'static,
U: ServiceFactory< U: ServiceFactory<
(Request, Framed<SslStream<TcpStream>, h1::Codec>),
Config = (), Config = (),
Request = (Request, Framed<SslStream<TcpStream>, h1::Codec>),
Response = (), Response = (),
>, >,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
<U::Service as Service>::Future: 'static, <U::Service as Service<(Request, Framed<SslStream<TcpStream>, h1::Codec>)>>::Future: 'static,
{ {
/// Create openssl based service /// Create openssl based service
pub fn openssl( pub fn openssl(
self, self,
acceptor: SslAcceptor, acceptor: SslAcceptor,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = TlsError<HandshakeError<TcpStream>, DispatchError>, Error = TlsError<SslError, DispatchError>,
InitError = (), InitError = (),
> { > {
pipeline_factory( pipeline_factory(
@ -250,39 +247,42 @@ mod openssl {
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
mod rustls { mod rustls {
use super::*;
use actix_tls::rustls::{Acceptor, ServerConfig, Session, TlsStream};
use actix_tls::TlsError;
use std::io; use std::io;
use actix_tls::accept::rustls::{Acceptor, ServerConfig, Session, TlsStream};
use actix_tls::accept::TlsError;
use super::*;
use actix_service::ServiceFactoryExt;
impl<S, B, X, U> HttpService<TlsStream<TcpStream>, S, B, X, U> impl<S, B, X, U> HttpService<TlsStream<TcpStream>, S, B, X, U>
where where
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
<X::Service as Service>::Future: 'static, <X::Service as Service<Request>>::Future: 'static,
U: ServiceFactory< U: ServiceFactory<
(Request, Framed<TlsStream<TcpStream>, h1::Codec>),
Config = (), Config = (),
Request = (Request, Framed<TlsStream<TcpStream>, h1::Codec>),
Response = (), Response = (),
>, >,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
<U::Service as Service>::Future: 'static, <U::Service as Service<(Request, Framed<TlsStream<TcpStream>, h1::Codec>)>>::Future: 'static,
{ {
/// Create openssl based service /// Create openssl based service
pub fn rustls( pub fn rustls(
self, self,
mut config: ServerConfig, mut config: ServerConfig,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
TcpStream,
Config = (), Config = (),
Request = TcpStream,
Response = (), Response = (),
Error = TlsError<io::Error, DispatchError>, Error = TlsError<io::Error, DispatchError>,
InitError = (), InitError = (),
@ -313,34 +313,30 @@ mod rustls {
} }
} }
impl<T, S, B, X, U> ServiceFactory for HttpService<T, S, B, X, U> impl<T, S, B, X, U> ServiceFactory<(T, Protocol, Option<net::SocketAddr>)>
for HttpService<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: ServiceFactory<Config = (), Request = Request>, S: ServiceFactory<Request, Config = ()>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: ServiceFactory<Config = (), Request = Request, Response = Request>, X: ServiceFactory<Request, Config = (), Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
<X::Service as Service>::Future: 'static, <X::Service as Service<Request>>::Future: 'static,
U: ServiceFactory< U: ServiceFactory<(Request, Framed<T, h1::Codec>), Config = (), Response = ()>,
Config = (),
Request = (Request, Framed<T, h1::Codec>),
Response = (),
>,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
<U::Service as Service>::Future: 'static, <U::Service as Service<(Request, Framed<T, h1::Codec>)>>::Future: 'static,
{ {
type Config = ();
type Request = (T, Protocol, Option<net::SocketAddr>);
type Response = (); type Response = ();
type Error = DispatchError; type Error = DispatchError;
type InitError = (); type Config = ();
type Service = HttpServiceHandler<T, S::Service, B, X::Service, U::Service>; type Service = HttpServiceHandler<T, S::Service, B, X::Service, U::Service>;
type InitError = ();
type Future = HttpServiceResponse<T, S, B, X, U>; type Future = HttpServiceResponse<T, S, B, X, U>;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {
@ -359,13 +355,12 @@ where
#[doc(hidden)] #[doc(hidden)]
#[pin_project] #[pin_project]
pub struct HttpServiceResponse< pub struct HttpServiceResponse<T, S, B, X, U>
T, where
S: ServiceFactory, S: ServiceFactory<Request>,
B, X: ServiceFactory<Request>,
X: ServiceFactory, U: ServiceFactory<(Request, Framed<T, h1::Codec>)>,
U: ServiceFactory, {
> {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
#[pin] #[pin]
@ -382,20 +377,20 @@ pub struct HttpServiceResponse<
impl<T, S, B, X, U> Future for HttpServiceResponse<T, S, B, X, U> impl<T, S, B, X, U> Future for HttpServiceResponse<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: ServiceFactory<Request = Request>, S: ServiceFactory<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: ServiceFactory<Request = Request, Response = Request>, X: ServiceFactory<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
X::InitError: fmt::Debug, X::InitError: fmt::Debug,
<X::Service as Service>::Future: 'static, <X::Service as Service<Request>>::Future: 'static,
U: ServiceFactory<Request = (Request, Framed<T, h1::Codec>), Response = ()>, U: ServiceFactory<(Request, Framed<T, h1::Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
U::InitError: fmt::Debug, U::InitError: fmt::Debug,
<U::Service as Service>::Future: 'static, <U::Service as Service<(Request, Framed<T, h1::Codec>)>>::Future: 'static,
{ {
type Output = type Output =
Result<HttpServiceHandler<T, S::Service, B, X::Service, U::Service>, ()>; Result<HttpServiceHandler<T, S::Service, B, X::Service, U::Service>, ()>;
@ -440,25 +435,30 @@ where
} }
/// `Service` implementation for http transport /// `Service` implementation for http transport
pub struct HttpServiceHandler<T, S: Service, B, X: Service, U: Service> { pub struct HttpServiceHandler<T, S, B, X, U>
where
S: Service<Request>,
X: Service<Request>,
U: Service<(Request, Framed<T, h1::Codec>)>,
{
srv: CloneableService<S>, srv: CloneableService<S>,
expect: CloneableService<X>, expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>, upgrade: Option<CloneableService<U>>,
cfg: ServiceConfig, cfg: ServiceConfig,
on_connect_ext: Option<Rc<ConnectCallback<T>>>, on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<(T, B, X)>, _t: PhantomData<B>,
} }
impl<T, S, B, X, U> HttpServiceHandler<T, S, B, X, U> impl<T, S, B, X, U> HttpServiceHandler<T, S, B, X, U>
where where
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>, U: Service<(Request, Framed<T, h1::Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
fn new( fn new(
@ -479,20 +479,20 @@ where
} }
} }
impl<T, S, B, X, U> Service for HttpServiceHandler<T, S, B, X, U> impl<T, S, B, X, U> Service<(T, Protocol, Option<net::SocketAddr>)>
for HttpServiceHandler<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>, U: Service<(Request, Framed<T, h1::Codec>), Response = ()>,
U::Error: fmt::Display + Into<Error>, U::Error: fmt::Display + Into<Error>,
{ {
type Request = (T, Protocol, Option<net::SocketAddr>);
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>;
@ -539,7 +539,10 @@ where
} }
} }
fn call(&mut self, (io, proto, peer_addr): Self::Request) -> Self::Future { fn call(
&mut self,
(io, proto, peer_addr): (T, Protocol, Option<net::SocketAddr>),
) -> Self::Future {
let mut connect_extensions = Extensions::new(); let mut connect_extensions = Extensions::new();
if let Some(ref handler) = self.on_connect_ext { if let Some(ref handler) = self.on_connect_ext {
@ -575,14 +578,14 @@ where
#[pin_project(project = StateProj)] #[pin_project(project = StateProj)]
enum State<T, S, B, X, U> enum State<T, S, B, X, U>
where where
S: Service<Request = Request>, S: Service<Request>,
S::Future: 'static, S::Future: 'static,
S::Error: Into<Error>, S::Error: Into<Error>,
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>, U: Service<(Request, Framed<T, h1::Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
H1(#[pin] h1::Dispatcher<T, S, B, X, U>), H1(#[pin] h1::Dispatcher<T, S, B, X, U>),
@ -602,14 +605,14 @@ where
pub struct HttpServiceHandlerResponse<T, S, B, X, U> pub struct HttpServiceHandlerResponse<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>, U: Service<(Request, Framed<T, h1::Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
#[pin] #[pin]
@ -619,14 +622,14 @@ where
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: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Future: 'static, S::Future: 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
B: MessageBody, B: MessageBody,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>, U: Service<(Request, Framed<T, h1::Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
type Output = Result<(), DispatchError>; type Output = Result<(), DispatchError>;
@ -639,13 +642,13 @@ where
impl<T, S, B, X, U> State<T, S, B, X, U> impl<T, S, B, X, U> State<T, S, B, X, U>
where where
T: AsyncRead + AsyncWrite + Unpin, T: AsyncRead + AsyncWrite + Unpin,
S: Service<Request = Request>, S: Service<Request>,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
X: Service<Request = Request, Response = Request>, X: Service<Request, Response = Request>,
X::Error: Into<Error>, X::Error: Into<Error>,
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>, U: Service<(Request, Framed<T, h1::Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
fn poll( fn poll(

View File

@ -10,7 +10,7 @@ use std::{
task::{Context, Poll}, task::{Context, Poll},
}; };
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use http::header::{self, HeaderName, HeaderValue}; use http::header::{self, HeaderName, HeaderValue};
use http::{Error as HttpError, Method, Uri, Version}; use http::{Error as HttpError, Method, Uri, Version};
@ -251,9 +251,11 @@ impl AsyncRead for TestBuffer {
fn poll_read( fn poll_read(
self: Pin<&mut Self>, self: Pin<&mut Self>,
_: &mut Context<'_>, _: &mut Context<'_>,
buf: &mut [u8], buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<usize>> { ) -> Poll<io::Result<()>> {
Poll::Ready(self.get_mut().read(buf)) let dst = buf.initialize_unfilled();
let res = self.get_mut().read(dst).map(|n| buf.advance(n));
Poll::Ready(res)
} }
} }
@ -356,11 +358,15 @@ impl AsyncRead for TestSeqBuffer {
fn poll_read( fn poll_read(
self: Pin<&mut Self>, self: Pin<&mut Self>,
_: &mut Context<'_>, _: &mut Context<'_>,
buf: &mut [u8], buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<usize>> { ) -> Poll<io::Result<()>> {
let r = self.get_mut().read(buf); let dst = buf.initialize_unfilled();
let r = self.get_mut().read(dst);
match r { match r {
Ok(n) => Poll::Ready(Ok(n)), Ok(n) => {
buf.advance(n);
Poll::Ready(Ok(()))
}
Err(err) if err.kind() == io::ErrorKind::WouldBlock => Poll::Pending, Err(err) if err.kind() == io::ErrorKind::WouldBlock => Poll::Pending,
Err(err) => Poll::Ready(Err(err)), Err(err) => Poll::Ready(Err(err)),
} }

View File

@ -11,7 +11,7 @@ use super::{Codec, Frame, Message};
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct Dispatcher<S, T> pub struct Dispatcher<S, T>
where where
S: Service<Request = Frame, Response = Message> + 'static, S: Service<Frame, Response = Message> + 'static,
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
{ {
#[pin] #[pin]
@ -21,17 +21,17 @@ where
impl<S, T> Dispatcher<S, T> impl<S, T> Dispatcher<S, T>
where where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
S: Service<Request = Frame, Response = Message>, S: Service<Frame, Response = Message>,
S::Future: 'static, S::Future: 'static,
S::Error: 'static, S::Error: 'static,
{ {
pub fn new<F: IntoService<S>>(io: T, service: F) -> Self { pub fn new<F: IntoService<S, Frame>>(io: T, service: F) -> Self {
Dispatcher { Dispatcher {
inner: InnerDispatcher::new(Framed::new(io, Codec::new()), service), inner: InnerDispatcher::new(Framed::new(io, Codec::new()), service),
} }
} }
pub fn with<F: IntoService<S>>(framed: Framed<T, Codec>, service: F) -> Self { pub fn with<F: IntoService<S, Frame>>(framed: Framed<T, Codec>, service: F) -> Self {
Dispatcher { Dispatcher {
inner: InnerDispatcher::new(framed, service), inner: InnerDispatcher::new(framed, service),
} }
@ -41,7 +41,7 @@ where
impl<S, T> Future for Dispatcher<S, T> impl<S, T> Future for Dispatcher<S, T>
where where
T: AsyncRead + AsyncWrite, T: AsyncRead + AsyncWrite,
S: Service<Request = Frame, Response = Message>, S: Service<Frame, Response = Message>,
S::Future: 'static, S::Future: 'static,
S::Error: 'static, S::Error: 'static,
{ {

View File

@ -1,9 +1,8 @@
use actix_service::ServiceFactory;
use bytes::Bytes;
use futures_util::future::{self, ok};
use actix_http::{http, HttpService, Request, Response}; use actix_http::{http, HttpService, Request, Response};
use actix_http_test::test_server; use actix_http_test::test_server;
use actix_service::ServiceFactoryExt;
use bytes::Bytes;
use futures_util::future::{self, ok};
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \

View File

@ -1,19 +1,17 @@
#![cfg(feature = "openssl")] #![cfg(feature = "openssl")]
use std::io; use std::io;
use actix_http_test::test_server;
use actix_service::{fn_service, ServiceFactory};
use bytes::{Bytes, BytesMut};
use futures_util::future::{err, ok, ready};
use futures_util::stream::{once, Stream, StreamExt};
use open_ssl::ssl::{AlpnError, SslAcceptor, SslFiletype, SslMethod};
use actix_http::error::{ErrorBadRequest, PayloadError}; use actix_http::error::{ErrorBadRequest, PayloadError};
use actix_http::http::header::{self, HeaderName, HeaderValue}; use actix_http::http::header::{self, HeaderName, HeaderValue};
use actix_http::http::{Method, StatusCode, Version}; use actix_http::http::{Method, StatusCode, Version};
use actix_http::httpmessage::HttpMessage; use actix_http::httpmessage::HttpMessage;
use actix_http::{body, Error, HttpService, Request, Response}; use actix_http::{body, Error, HttpService, Request, Response};
use actix_http_test::test_server;
use actix_service::{fn_service, ServiceFactoryExt};
use bytes::{Bytes, BytesMut};
use futures_util::future::{err, ok, ready};
use futures_util::stream::{once, Stream, StreamExt};
use open_ssl::ssl::{AlpnError, SslAcceptor, SslFiletype, SslMethod};
async fn load_body<S>(stream: S) -> Result<BytesMut, PayloadError> async fn load_body<S>(stream: S) -> Result<BytesMut, PayloadError>
where where

View File

@ -3,7 +3,7 @@ use std::time::Duration;
use std::{net, thread}; use std::{net, thread};
use actix_http_test::test_server; use actix_http_test::test_server;
use actix_rt::time::delay_for; use actix_rt::time::sleep;
use actix_service::fn_service; use actix_service::fn_service;
use bytes::Bytes; use bytes::Bytes;
use futures_util::future::{self, err, ok, ready, FutureExt}; use futures_util::future::{self, err, ok, ready, FutureExt};
@ -88,7 +88,7 @@ async fn test_expect_continue_h1() {
let srv = test_server(|| { let srv = test_server(|| {
HttpService::build() HttpService::build()
.expect(fn_service(|req: Request| { .expect(fn_service(|req: Request| {
delay_for(Duration::from_millis(20)).then(move |_| { sleep(Duration::from_millis(20)).then(move |_| {
if req.head().uri.query() == Some("yes=") { if req.head().uri.query() == Some("yes=") {
ok(req) ok(req)
} else { } else {

View File

@ -36,11 +36,10 @@ impl<T> Clone for WsService<T> {
} }
} }
impl<T> Service for WsService<T> impl<T> Service<(Request, Framed<T, h1::Codec>)> for WsService<T>
where where
T: AsyncRead + AsyncWrite + Unpin + 'static, T: AsyncRead + AsyncWrite + Unpin + 'static,
{ {
type Request = (Request, Framed<T, h1::Codec>);
type Response = (); type Response = ();
type Error = Error; type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<(), Error>>>>; type Future = Pin<Box<dyn Future<Output = Result<(), Error>>>>;
@ -50,7 +49,10 @@ where
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
fn call(&mut self, (req, mut framed): Self::Request) -> Self::Future { fn call(
&mut self,
(req, mut framed): (Request, Framed<T, h1::Codec>),
) -> Self::Future {
let fut = async move { let fut = async move {
let res = ws::handshake(req.head()).unwrap().message_body(()); let res = ws::handshake(req.head()).unwrap().message_body(());

View File

@ -2,6 +2,9 @@
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
* Fix multipart consuming payload before header checks #1513 * Fix multipart consuming payload before header checks #1513
* Update `bytes` to `1.0`. [#1813]
[#1813]: https://github.com/actix/actix-web/pull/1813
## 3.0.0 - 2020-09-11 ## 3.0.0 - 2020-09-11

View File

@ -17,16 +17,16 @@ path = "src/lib.rs"
[dependencies] [dependencies]
actix-web = { version = "3.0.0", default-features = false } actix-web = { version = "3.0.0", default-features = false }
actix-service = "1.0.6" actix-utils = "3.0.0-beta.1"
actix-utils = "2.0.0"
bytes = "0.5.3" bytes = "1"
derive_more = "0.99.2" derive_more = "0.99.2"
httparse = "1.3" httparse = "1.3"
futures-util = { version = "0.3.5", default-features = false } futures-util = { version = "0.3.7", default-features = false }
log = "0.4" log = "0.4"
mime = "0.3" mime = "0.3"
twoway = "0.2" twoway = "0.2"
[dev-dependencies] [dev-dependencies]
actix-rt = "1.0.0" actix-rt = "2.0.0-beta.1"
actix-http = "2.0.0" actix-http = "2.0.0"

View File

@ -1,8 +1,10 @@
# Changes # Changes
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
* Upgrade `pin-project` to `1.0`. * Update `pin-project` to `1.0`.
* Update `bytes` to `1.0`. [#1813]
[#1813]: https://github.com/actix/actix-web/pull/1813
## 3.0.0 - 2020-09-11 ## 3.0.0 - 2020-09-11
* No significant changes from `3.0.0-beta.2`. * No significant changes from `3.0.0-beta.2`.

View File

@ -16,16 +16,17 @@ name = "actix_web_actors"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
actix = "0.10.0" actix = "0.11.0-beta.1"
actix-web = { version = "3.0.0", default-features = false } actix-codec = "0.4.0-beta.1"
actix-http = "2.0.0" actix-http = "2.0.0"
actix-codec = "0.3.0" actix-web = { version = "3.0.0", default-features = false }
bytes = "0.5.2"
futures-channel = { version = "0.3.5", default-features = false } bytes = "1"
futures-core = { version = "0.3.5", default-features = false } futures-core = { version = "0.3.7", default-features = false }
pin-project = "1.0.0" pin-project = "1.0.0"
tokio = { version = "1", features = ["sync"] }
[dev-dependencies] [dev-dependencies]
actix-rt = "1.1.1" actix-rt = "2.0.0-beta.1"
env_logger = "0.7" env_logger = "0.7"
futures-util = { version = "0.3.5", default-features = false } futures-util = { version = "0.3.7", default-features = false }

View File

@ -12,8 +12,8 @@ use actix::{
}; };
use actix_web::error::Error; use actix_web::error::Error;
use bytes::Bytes; use bytes::Bytes;
use futures_channel::oneshot::Sender;
use futures_core::Stream; use futures_core::Stream;
use tokio::sync::oneshot::Sender;
/// Execution context for http actors /// Execution context for http actors
pub struct HttpContext<A> pub struct HttpContext<A>

View File

@ -24,8 +24,8 @@ use actix_web::error::{Error, PayloadError};
use actix_web::http::{header, Method, StatusCode}; use actix_web::http::{header, Method, StatusCode};
use actix_web::{HttpRequest, HttpResponse}; use actix_web::{HttpRequest, HttpResponse};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures_channel::oneshot::Sender;
use futures_core::Stream; use futures_core::Stream;
use tokio::sync::oneshot::Sender;
/// Do websocket handshake and start ws actor. /// Do websocket handshake and start ws actor.
pub fn start<A, T>(actor: A, req: &HttpRequest, stream: T) -> Result<HttpResponse, Error> pub fn start<A, T>(actor: A, req: &HttpRequest, stream: T) -> Result<HttpResponse, Error>

View File

@ -19,8 +19,8 @@ syn = { version = "1", features = ["full", "parsing"] }
proc-macro2 = "1" proc-macro2 = "1"
[dev-dependencies] [dev-dependencies]
actix-rt = "1.1.1" actix-rt = "2.0.0-beta.1"
actix-web = "3.0.0" actix-web = "3.0.0"
futures-util = { version = "0.3.5", default-features = false } futures-util = { version = "0.3.7", default-features = false }
trybuild = "1" trybuild = "1"
rustversion = "1" rustversion = "1"

View File

@ -88,17 +88,16 @@ async fn route_test() -> impl Responder {
pub struct ChangeStatusCode; pub struct ChangeStatusCode;
impl<S, B> Transform<S> for ChangeStatusCode impl<S, B> Transform<S, ServiceRequest> for ChangeStatusCode
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
B: 'static, B: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type InitError = ();
type Transform = ChangeStatusCodeMiddleware<S>; type Transform = ChangeStatusCodeMiddleware<S>;
type InitError = ();
type Future = future::Ready<Result<Self::Transform, Self::InitError>>; type Future = future::Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
@ -110,13 +109,12 @@ pub struct ChangeStatusCodeMiddleware<S> {
service: S, service: S,
} }
impl<S, B> Service for ChangeStatusCodeMiddleware<S> impl<S, B> Service<ServiceRequest> for ChangeStatusCodeMiddleware<S>
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
B: 'static, B: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]

View File

@ -2,7 +2,11 @@
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
### Changed ### Changed
* Bumped `rand` to `0.8` * Update `rand` to `0.8`
* Update `bytes` to `1.0`. [#1813]
* Update `rust-tls` to `0.19`. [#1813]
[#1813]: https://github.com/actix/actix-web/pull/1813
## 2.0.3 - 2020-11-29 ## 2.0.3 - 2020-11-29

View File

@ -37,16 +37,16 @@ rustls = ["rust-tls", "actix-http/rustls"]
compress = ["actix-http/compress"] compress = ["actix-http/compress"]
[dependencies] [dependencies]
actix-codec = "0.3.0" actix-codec = "0.4.0-beta.1"
actix-service = "1.0.6" actix-service = "2.0.0-beta.2"
actix-http = "2.2.0" actix-http = "2.2.0"
actix-rt = "1.0.0" actix-rt = "2.0.0-beta.1"
base64 = "0.13" base64 = "0.13"
bytes = "0.5.3" bytes = "1"
cfg-if = "1.0" cfg-if = "1.0"
derive_more = "0.99.2" derive_more = "0.99.2"
futures-core = { version = "0.3.5", default-features = false } futures-core = { version = "0.3.7", default-features = false }
log =" 0.4" log =" 0.4"
mime = "0.3" mime = "0.3"
percent-encoding = "2.1" percent-encoding = "2.1"
@ -55,18 +55,20 @@ serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
serde_urlencoded = "0.7" serde_urlencoded = "0.7"
open-ssl = { version = "0.10", package = "openssl", optional = true } open-ssl = { version = "0.10", package = "openssl", optional = true }
rust-tls = { version = "0.18.0", package = "rustls", optional = true, features = ["dangerous_configuration"] } rust-tls = { version = "0.19.0", package = "rustls", optional = true, features = ["dangerous_configuration"] }
[dev-dependencies] [dev-dependencies]
actix-connect = { version = "2.0.0", features = ["openssl"] } # TODO: actix is temporary added as dev dep for actix-macro reason.
# Can be removed when it does not impact tests.
actix = "0.11.0-beta.1"
actix-web = { version = "3.0.0", features = ["openssl"] } actix-web = { version = "3.0.0", features = ["openssl"] }
actix-http = { version = "2.0.0", features = ["openssl"] } actix-http = { version = "2.0.0", features = ["openssl"] }
actix-http-test = { version = "2.0.0", features = ["openssl"] } actix-http-test = { version = "2.0.0", features = ["openssl"] }
actix-utils = "2.0.0" actix-utils = "3.0.0-beta.1"
actix-server = "1.0.0" actix-server = "2.0.0-beta.2"
actix-tls = { version = "2.0.0", features = ["openssl", "rustls"] } actix-tls = { version = "3.0.0-beta.2", features = ["openssl", "rustls"] }
brotli2 = "0.3.2" brotli2 = "0.3.2"
flate2 = "1.0.13" flate2 = "1.0.13"
futures-util = { version = "0.3.5", default-features = false } futures-util = { version = "0.3.7", default-features = false }
env_logger = "0.7" env_logger = "0.7"
webpki = "0.21" webpki = "0.21"

View File

@ -51,7 +51,7 @@ impl ClientBuilder {
/// Use custom connector service. /// Use custom connector service.
pub fn connector<T>(mut self, connector: T) -> Self pub fn connector<T>(mut self, connector: T) -> Self
where where
T: Service<Request = HttpConnect, Error = ConnectError> + 'static, T: Service<HttpConnect, Error = ConnectError> + 'static,
T::Response: Connection, T::Response: Connection,
<T::Response as Connection>::Future: 'static, <T::Response as Connection>::Future: 'static,
T::Future: 'static, T::Future: 'static,

View File

@ -2,9 +2,9 @@ use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::{fmt, io, mem, net}; use std::{fmt, io, net};
use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_codec::{AsyncRead, AsyncWrite, Framed, ReadBuf};
use actix_http::body::Body; use actix_http::body::Body;
use actix_http::client::{ use actix_http::client::{
Connect as ClientConnect, ConnectError, Connection, SendRequestError, Connect as ClientConnect, ConnectError, Connection, SendRequestError,
@ -70,7 +70,7 @@ pub(crate) trait Connect {
impl<T> Connect for ConnectorWrapper<T> impl<T> Connect for ConnectorWrapper<T>
where where
T: Service<Request = ClientConnect, Error = ConnectError>, T: Service<ClientConnect, Error = ConnectError>,
T::Response: Connection, T::Response: Connection,
<T::Response as Connection>::Io: 'static, <T::Response as Connection>::Io: 'static,
<T::Response as Connection>::Future: 'static, <T::Response as Connection>::Future: 'static,
@ -221,18 +221,11 @@ impl fmt::Debug for BoxedSocket {
} }
impl AsyncRead for BoxedSocket { impl AsyncRead for BoxedSocket {
unsafe fn prepare_uninitialized_buffer(
&self,
buf: &mut [mem::MaybeUninit<u8>],
) -> bool {
self.0.as_read().prepare_uninitialized_buffer(buf)
}
fn poll_read( fn poll_read(
self: Pin<&mut Self>, self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,
buf: &mut [u8], buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<usize>> { ) -> Poll<io::Result<()>> {
Pin::new(self.get_mut().0.as_read_mut()).poll_read(cx, buf) Pin::new(self.get_mut().0.as_read_mut()).poll_read(cx, buf)
} }
} }

View File

@ -5,7 +5,7 @@ use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::Duration; use std::time::Duration;
use actix_rt::time::{delay_for, Delay}; use actix_rt::time::{sleep, Sleep};
use bytes::Bytes; use bytes::Bytes;
use derive_more::From; use derive_more::From;
use futures_core::Stream; use futures_core::Stream;
@ -56,7 +56,8 @@ impl Into<SendRequestError> for PrepForSendingError {
pub enum SendClientRequest { pub enum SendClientRequest {
Fut( Fut(
Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>, Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>,
Option<Delay>, // FIXME: use a pinned Sleep instead of box.
Option<Pin<Box<Sleep>>>,
bool, bool,
), ),
Err(Option<SendRequestError>), Err(Option<SendRequestError>),
@ -68,7 +69,7 @@ impl SendClientRequest {
response_decompress: bool, response_decompress: bool,
timeout: Option<Duration>, timeout: Option<Duration>,
) -> SendClientRequest { ) -> SendClientRequest {
let delay = timeout.map(delay_for); let delay = timeout.map(|d| Box::pin(sleep(d)));
SendClientRequest::Fut(send, delay, response_decompress) SendClientRequest::Fut(send, delay, response_decompress)
} }
} }

View File

@ -108,14 +108,14 @@ async fn test_form() {
async fn test_timeout() { async fn test_timeout() {
let srv = test::start(|| { let srv = test::start(|| {
App::new().service(web::resource("/").route(web::to(|| async { App::new().service(web::resource("/").route(web::to(|| async {
actix_rt::time::delay_for(Duration::from_millis(200)).await; actix_rt::time::sleep(Duration::from_millis(200)).await;
Ok::<_, Error>(HttpResponse::Ok().body(STR)) Ok::<_, Error>(HttpResponse::Ok().body(STR))
}))) })))
}); });
let connector = awc::Connector::new() let connector = awc::Connector::new()
.connector(actix_connect::new_connector( .connector(actix_tls::connect::new_connector(
actix_connect::start_default_resolver().await.unwrap(), actix_tls::connect::start_default_resolver().await.unwrap(),
)) ))
.timeout(Duration::from_secs(15)) .timeout(Duration::from_secs(15))
.finish(); .finish();
@ -136,7 +136,7 @@ async fn test_timeout() {
async fn test_timeout_override() { async fn test_timeout_override() {
let srv = test::start(|| { let srv = test::start(|| {
App::new().service(web::resource("/").route(web::to(|| async { App::new().service(web::resource("/").route(web::to(|| async {
actix_rt::time::delay_for(Duration::from_millis(200)).await; actix_rt::time::sleep(Duration::from_millis(200)).await;
Ok::<_, Error>(HttpResponse::Ok().body(STR)) Ok::<_, Error>(HttpResponse::Ok().body(STR))
}))) })))
}); });

View File

@ -1,7 +1,7 @@
#![cfg(feature = "openssl")] #![cfg(feature = "openssl")]
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::test_server; use actix_http_test::test_server;
use actix_service::{map_config, ServiceFactory}; use actix_service::{map_config, ServiceFactoryExt};
use actix_web::http::Version; use actix_web::http::Version;
use actix_web::{dev::AppConfig, web, App, HttpResponse}; use actix_web::{dev::AppConfig, web, App, HttpResponse};
use open_ssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode}; use open_ssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode};

View File

@ -4,7 +4,7 @@ use std::sync::Arc;
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::test_server; use actix_http_test::test_server;
use actix_service::{map_config, pipeline_factory, ServiceFactory}; use actix_service::{map_config, pipeline_factory, ServiceFactoryExt};
use actix_web::http::Version; use actix_web::http::Version;
use actix_web::{dev::AppConfig, web, App, HttpResponse}; use actix_web::{dev::AppConfig, web, App, HttpResponse};
use futures_util::future::ok; use futures_util::future::ok;

View File

@ -4,7 +4,7 @@ use std::sync::Arc;
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::test_server; use actix_http_test::test_server;
use actix_service::{map_config, pipeline_factory, ServiceFactory}; use actix_service::{map_config, pipeline_factory, ServiceFactoryExt};
use actix_web::http::Version; use actix_web::http::Version;
use actix_web::{dev::AppConfig, web, App, HttpResponse}; use actix_web::{dev::AppConfig, web, App, HttpResponse};
use futures_util::future::ok; use futures_util::future::ok;

View File

@ -29,18 +29,22 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
fn bench_async_burst(c: &mut Criterion) { fn bench_async_burst(c: &mut Criterion) {
// We are using System here, since Runtime requires preinitialized tokio // We are using System here, since Runtime requires preinitialized tokio
// Maybe add to actix_rt docs // Maybe add to actix_rt docs
let mut rt = actix_rt::System::new("test"); let rt = actix_rt::System::new("test");
let srv = test::start(|| { let srv = rt.block_on(async {
App::new() test::start(|| {
.service(web::resource("/").route(web::to(|| HttpResponse::Ok().body(STR)))) App::new().service(
web::resource("/").route(web::to(|| HttpResponse::Ok().body(STR))),
)
})
}); });
let url = srv.url("/"); let url = srv.url("/");
c.bench_function("get_body_async_burst", move |b| { c.bench_function("get_body_async_burst", move |b| {
b.iter_custom(|iters| { b.iter_custom(|iters| {
let client = Client::new().get(url.clone()).freeze().unwrap(); let client =
rt.block_on(async { Client::new().get(url.clone()).freeze().unwrap() });
let start = std::time::Instant::now(); let start = std::time::Instant::now();
// benchmark body // benchmark body

View File

@ -23,10 +23,9 @@ use actix_web::test::{init_service, ok_service, TestRequest};
/// async_service_direct time: [1.0908 us 1.1656 us 1.2613 us] /// async_service_direct time: [1.0908 us 1.1656 us 1.2613 us]
pub fn bench_async_service<S>(c: &mut Criterion, srv: S, name: &str) pub fn bench_async_service<S>(c: &mut Criterion, srv: S, name: &str)
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse, Error = Error> S: Service<ServiceRequest, Response = ServiceResponse, Error = Error> + 'static,
+ 'static,
{ {
let mut rt = actix_rt::System::new("test"); let rt = actix_rt::System::new("test");
let srv = Rc::new(RefCell::new(srv)); let srv = Rc::new(RefCell::new(srv));
let req = TestRequest::default().to_srv_request(); let req = TestRequest::default().to_srv_request();
@ -41,14 +40,15 @@ where
b.iter_custom(|iters| { b.iter_custom(|iters| {
let srv = srv.clone(); let srv = srv.clone();
// exclude request generation, it appears it takes significant time vs call (3us vs 1us) // exclude request generation, it appears it takes significant time vs call (3us vs 1us)
let reqs: Vec<_> = (0..iters) let futs = (0..iters)
.map(|_| TestRequest::default().to_srv_request()) .map(|_| TestRequest::default().to_srv_request())
.collect(); .map(|req| srv.borrow_mut().call(req));
let start = std::time::Instant::now(); let start = std::time::Instant::now();
// benchmark body // benchmark body
rt.block_on(async move { rt.block_on(async move {
for req in reqs { for fut in futs {
srv.borrow_mut().call(req).await.unwrap(); fut.await.unwrap();
} }
}); });
let elapsed = start.elapsed(); let elapsed = start.elapsed();
@ -67,7 +67,7 @@ async fn index(req: ServiceRequest) -> Result<ServiceResponse, Error> {
// Sample results on MacBook Pro '14 // Sample results on MacBook Pro '14
// time: [2.0724 us 2.1345 us 2.2074 us] // time: [2.0724 us 2.1345 us 2.2074 us]
fn async_web_service(c: &mut Criterion) { fn async_web_service(c: &mut Criterion) {
let mut rt = actix_rt::System::new("test"); let rt = actix_rt::System::new("test");
let srv = Rc::new(RefCell::new(rt.block_on(init_service( let srv = Rc::new(RefCell::new(rt.block_on(init_service(
App::new().service(web::service("/").finish(index)), App::new().service(web::service("/").finish(index)),
)))); ))));
@ -83,13 +83,14 @@ fn async_web_service(c: &mut Criterion) {
c.bench_function("async_web_service_direct", move |b| { c.bench_function("async_web_service_direct", move |b| {
b.iter_custom(|iters| { b.iter_custom(|iters| {
let srv = srv.clone(); let srv = srv.clone();
let reqs = (0..iters).map(|_| TestRequest::get().uri("/").to_request()); let futs = (0..iters)
.map(|_| TestRequest::get().uri("/").to_request())
.map(|req| srv.borrow_mut().call(req));
let start = std::time::Instant::now(); let start = std::time::Instant::now();
// benchmark body // benchmark body
rt.block_on(async move { rt.block_on(async move {
for req in reqs { for fut in futs {
srv.borrow_mut().call(req).await.unwrap(); fut.await.unwrap();
} }
}); });
let elapsed = start.elapsed(); let elapsed = start.elapsed();

View File

@ -5,10 +5,11 @@ use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use actix_http::body::{Body, MessageBody}; use actix_http::body::{Body, MessageBody};
use actix_http::Extensions; use actix_http::{Extensions, Request};
use actix_service::boxed::{self, BoxServiceFactory}; use actix_service::boxed::{self, BoxServiceFactory};
use actix_service::{ use actix_service::{
apply, apply_fn_factory, IntoServiceFactory, ServiceFactory, Transform, apply, apply_fn_factory, IntoServiceFactory, ServiceFactory, ServiceFactoryExt,
Transform,
}; };
use futures_util::future::FutureExt; use futures_util::future::FutureExt;
@ -63,8 +64,8 @@ impl<T, B> App<T, B>
where where
B: MessageBody, B: MessageBody,
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -268,10 +269,10 @@ where
/// ``` /// ```
pub fn default_service<F, U>(mut self, f: F) -> Self pub fn default_service<F, U>(mut self, f: F) -> Self
where where
F: IntoServiceFactory<U>, F: IntoServiceFactory<U, ServiceRequest>,
U: ServiceFactory< U: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
> + 'static, > + 'static,
@ -353,8 +354,8 @@ where
mw: M, mw: M,
) -> App< ) -> App<
impl ServiceFactory< impl ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B1>, Response = ServiceResponse<B1>,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -364,7 +365,7 @@ where
where where
M: Transform< M: Transform<
T::Service, T::Service,
Request = ServiceRequest, ServiceRequest,
Response = ServiceResponse<B1>, Response = ServiceResponse<B1>,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -420,8 +421,8 @@ where
mw: F, mw: F,
) -> App< ) -> App<
impl ServiceFactory< impl ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B1>, Response = ServiceResponse<B1>,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -447,12 +448,12 @@ where
} }
} }
impl<T, B> IntoServiceFactory<AppInit<T, B>> for App<T, B> impl<T, B> IntoServiceFactory<AppInit<T, B>, Request> for App<T, B>
where where
B: MessageBody, B: MessageBody,
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = Error, Error = Error,
InitError = (), InitError = (),

View File

@ -29,8 +29,8 @@ type BoxResponse = LocalBoxFuture<'static, Result<ServiceResponse, Error>>;
pub struct AppInit<T, B> pub struct AppInit<T, B>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -46,22 +46,21 @@ where
pub(crate) external: RefCell<Vec<ResourceDef>>, pub(crate) external: RefCell<Vec<ResourceDef>>,
} }
impl<T, B> ServiceFactory for AppInit<T, B> impl<T, B> ServiceFactory<Request> for AppInit<T, B>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = Error, Error = Error,
InitError = (), InitError = (),
>, >,
{ {
type Config = AppConfig;
type Request = Request;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = T::Error; type Error = T::Error;
type InitError = T::InitError; type Config = AppConfig;
type Service = AppInitService<T::Service, B>; type Service = AppInitService<T::Service, B>;
type InitError = T::InitError;
type Future = AppInitResult<T, B>; type Future = AppInitResult<T, B>;
fn new_service(&self, config: AppConfig) -> Self::Future { fn new_service(&self, config: AppConfig) -> Self::Future {
@ -132,7 +131,7 @@ where
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct AppInitResult<T, B> pub struct AppInitResult<T, B>
where where
T: ServiceFactory, T: ServiceFactory<ServiceRequest>,
{ {
#[pin] #[pin]
endpoint_fut: T::Future, endpoint_fut: T::Future,
@ -155,8 +154,8 @@ where
impl<T, B> Future for AppInitResult<T, B> impl<T, B> Future for AppInitResult<T, B>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -214,7 +213,7 @@ where
/// Service to convert `Request` to a `ServiceRequest<S>` /// Service to convert `Request` to a `ServiceRequest<S>`
pub struct AppInitService<T, B> pub struct AppInitService<T, B>
where where
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, T: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
service: T, service: T,
rmap: Rc<ResourceMap>, rmap: Rc<ResourceMap>,
@ -223,11 +222,10 @@ where
pool: &'static HttpRequestPool, pool: &'static HttpRequestPool,
} }
impl<T, B> Service for AppInitService<T, B> impl<T, B> Service<Request> for AppInitService<T, B>
where where
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, T: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Request = Request;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = T::Error; type Error = T::Error;
type Future = T::Future; type Future = T::Future;
@ -263,7 +261,7 @@ where
impl<T, B> Drop for AppInitService<T, B> impl<T, B> Drop for AppInitService<T, B>
where where
T: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, T: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
fn drop(&mut self) { fn drop(&mut self) {
self.pool.clear(); self.pool.clear();
@ -275,9 +273,8 @@ pub struct AppRoutingFactory {
default: Rc<HttpNewService>, default: Rc<HttpNewService>,
} }
impl ServiceFactory for AppRoutingFactory { impl ServiceFactory<ServiceRequest> for AppRoutingFactory {
type Config = (); type Config = ();
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
@ -386,8 +383,7 @@ pub struct AppRouting {
default: Option<HttpService>, default: Option<HttpService>,
} }
impl Service for AppRouting { impl Service<ServiceRequest> for AppRouting {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = BoxResponse; type Future = BoxResponse;
@ -434,9 +430,8 @@ impl AppEntry {
} }
} }
impl ServiceFactory for AppEntry { impl ServiceFactory<ServiceRequest> for AppEntry {
type Config = (); type Config = ();
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();

View File

@ -105,10 +105,10 @@ impl AppService {
factory: F, factory: F,
nested: Option<Rc<ResourceMap>>, nested: Option<Rc<ResourceMap>>,
) where ) where
F: IntoServiceFactory<S>, F: IntoServiceFactory<S, ServiceRequest>,
S: ServiceFactory< S: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),

View File

@ -82,14 +82,13 @@ where
} }
} }
impl<F, T, R> ServiceFactory for HandlerService<F, T, R> impl<F, T, R> ServiceFactory<ServiceRequest> for HandlerService<F, T, R>
where where
F: Handler<T, R>, F: Handler<T, R>,
T: FromRequest, T: FromRequest,
R: Future, R: Future,
R::Output: Responder, R::Output: Responder,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Config = (); type Config = ();
@ -102,15 +101,14 @@ where
} }
} }
// Handler is both it's ServiceHandler and Service Type. // HandlerService is both it's ServiceFactory and Service Type.
impl<F, T, R> Service for HandlerService<F, T, R> impl<F, T, R> Service<ServiceRequest> for HandlerService<F, T, R>
where where
F: Handler<T, R>, F: Handler<T, R>,
T: FromRequest, T: FromRequest,
R: Future, R: Future,
R::Output: Responder, R::Output: Responder,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = HandlerServiceFuture<F, T, R>; type Future = HandlerServiceFuture<F, T, R>;
@ -119,7 +117,7 @@ where
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }
fn call(&mut self, req: Self::Request) -> Self::Future { fn call(&mut self, req: ServiceRequest) -> Self::Future {
let (req, mut payload) = req.into_parts(); let (req, mut payload) = req.into_parts();
let fut = T::from_request(&req, &mut payload); let fut = T::from_request(&req, &mut payload);
HandlerServiceFuture::Extract(fut, Some(req), self.hnd.clone()) HandlerServiceFuture::Extract(fut, Some(req), self.hnd.clone())

View File

@ -51,16 +51,15 @@ impl Default for Compress {
} }
} }
impl<S, B> Transform<S> for Compress impl<S, B> Transform<S, ServiceRequest> for Compress
where where
B: MessageBody, B: MessageBody,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<Encoder<B>>; type Response = ServiceResponse<Encoder<B>>;
type Error = Error; type Error = Error;
type InitError = ();
type Transform = CompressMiddleware<S>; type Transform = CompressMiddleware<S>;
type InitError = ();
type Future = Ready<Result<Self::Transform, Self::InitError>>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
@ -76,12 +75,11 @@ pub struct CompressMiddleware<S> {
encoding: ContentEncoding, encoding: ContentEncoding,
} }
impl<S, B> Service for CompressMiddleware<S> impl<S, B> Service<ServiceRequest> for CompressMiddleware<S>
where where
B: MessageBody, B: MessageBody,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<Encoder<B>>; type Response = ServiceResponse<Encoder<B>>;
type Error = Error; type Error = Error;
type Future = CompressResponse<S, B>; type Future = CompressResponse<S, B>;
@ -115,7 +113,7 @@ where
#[pin_project] #[pin_project]
pub struct CompressResponse<S, B> pub struct CompressResponse<S, B>
where where
S: Service, S: Service<ServiceRequest>,
B: MessageBody, B: MessageBody,
{ {
#[pin] #[pin]
@ -127,7 +125,7 @@ where
impl<S, B> Future for CompressResponse<S, B> impl<S, B> Future for CompressResponse<S, B>
where where
B: MessageBody, B: MessageBody,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Output = Result<ServiceResponse<Encoder<B>>, Error>; type Output = Result<ServiceResponse<Encoder<B>>, Error>;

View File

@ -31,19 +31,18 @@ impl<T> Condition<T> {
} }
} }
impl<S, T> Transform<S> for Condition<T> impl<S, T, Req> Transform<S, Req> for Condition<T>
where where
S: Service + 'static, S: Service<Req> + 'static,
T: Transform<S, Request = S::Request, Response = S::Response, Error = S::Error>, T: Transform<S, Req, Response = S::Response, Error = S::Error>,
T::Future: 'static, T::Future: 'static,
T::InitError: 'static, T::InitError: 'static,
T::Transform: 'static, T::Transform: 'static,
{ {
type Request = S::Request;
type Response = S::Response; type Response = S::Response;
type Error = S::Error; type Error = S::Error;
type InitError = T::InitError;
type Transform = ConditionMiddleware<T::Transform, S>; type Transform = ConditionMiddleware<T::Transform, S>;
type InitError = T::InitError;
type Future = LocalBoxFuture<'static, Result<Self::Transform, Self::InitError>>; type Future = LocalBoxFuture<'static, Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
@ -66,12 +65,11 @@ pub enum ConditionMiddleware<E, D> {
Disable(D), Disable(D),
} }
impl<E, D> Service for ConditionMiddleware<E, D> impl<E, D, Req> Service<Req> for ConditionMiddleware<E, D>
where where
E: Service, E: Service<Req>,
D: Service<Request = E::Request, Response = E::Response, Error = E::Error>, D: Service<Req, Response = E::Response, Error = E::Error>,
{ {
type Request = E::Request;
type Response = E::Response; type Response = E::Response;
type Error = E::Error; type Error = E::Error;
type Future = Either<E::Future, D::Future>; type Future = Either<E::Future, D::Future>;
@ -84,7 +82,7 @@ where
} }
} }
fn call(&mut self, req: E::Request) -> Self::Future { fn call(&mut self, req: Req) -> Self::Future {
use ConditionMiddleware::*; use ConditionMiddleware::*;
match self { match self {
Enable(service) => Either::Left(service.call(req)), Enable(service) => Either::Left(service.call(req)),

View File

@ -93,12 +93,11 @@ impl DefaultHeaders {
} }
} }
impl<S, B> Transform<S> for DefaultHeaders impl<S, B> Transform<S, ServiceRequest> for DefaultHeaders
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type Transform = DefaultHeadersMiddleware<S>; type Transform = DefaultHeadersMiddleware<S>;
@ -118,12 +117,11 @@ pub struct DefaultHeadersMiddleware<S> {
inner: Rc<Inner>, inner: Rc<Inner>,
} }
impl<S, B> Service for DefaultHeadersMiddleware<S> impl<S, B> Service<ServiceRequest> for DefaultHeadersMiddleware<S>
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type Future = DefaultHeaderFuture<S, B>; type Future = DefaultHeaderFuture<S, B>;
@ -145,7 +143,7 @@ where
} }
#[pin_project::pin_project] #[pin_project::pin_project]
pub struct DefaultHeaderFuture<S: Service, B> { pub struct DefaultHeaderFuture<S: Service<ServiceRequest>, B> {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
inner: Rc<Inner>, inner: Rc<Inner>,
@ -154,7 +152,7 @@ pub struct DefaultHeaderFuture<S: Service, B> {
impl<S, B> Future for DefaultHeaderFuture<S, B> impl<S, B> Future for DefaultHeaderFuture<S, B>
where where
S: Service<Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Output = <S::Future as Future>::Output; type Output = <S::Future as Future>::Output;

View File

@ -81,17 +81,16 @@ impl<B> ErrorHandlers<B> {
} }
} }
impl<S, B> Transform<S> for ErrorHandlers<B> impl<S, B> Transform<S, ServiceRequest> for ErrorHandlers<B>
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
B: 'static, B: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type InitError = ();
type Transform = ErrorHandlersMiddleware<S, B>; type Transform = ErrorHandlersMiddleware<S, B>;
type InitError = ();
type Future = Ready<Result<Self::Transform, Self::InitError>>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
@ -108,13 +107,12 @@ pub struct ErrorHandlersMiddleware<S, B> {
handlers: Rc<FxHashMap<StatusCode, Box<ErrorHandler<B>>>>, handlers: Rc<FxHashMap<StatusCode, Box<ErrorHandler<B>>>>,
} }
impl<S, B> Service for ErrorHandlersMiddleware<S, B> impl<S, B> Service<ServiceRequest> for ErrorHandlersMiddleware<S, B>
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
B: 'static, B: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;

View File

@ -179,12 +179,11 @@ impl Default for Logger {
} }
} }
impl<S, B> Transform<S> for Logger impl<S, B> Transform<S, ServiceRequest> for Logger
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
B: MessageBody, B: MessageBody,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<StreamLog<B>>; type Response = ServiceResponse<StreamLog<B>>;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
@ -216,12 +215,11 @@ pub struct LoggerMiddleware<S> {
service: S, service: S,
} }
impl<S, B> Service for LoggerMiddleware<S> impl<S, B> Service<ServiceRequest> for LoggerMiddleware<S>
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
B: MessageBody, B: MessageBody,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<StreamLog<B>>; type Response = ServiceResponse<StreamLog<B>>;
type Error = Error; type Error = Error;
type Future = LoggerResponse<S, B>; type Future = LoggerResponse<S, B>;
@ -262,19 +260,19 @@ where
pub struct LoggerResponse<S, B> pub struct LoggerResponse<S, B>
where where
B: MessageBody, B: MessageBody,
S: Service, S: Service<ServiceRequest>,
{ {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
time: OffsetDateTime, time: OffsetDateTime,
format: Option<Format>, format: Option<Format>,
_t: PhantomData<(B,)>, _t: PhantomData<B>,
} }
impl<S, B> Future for LoggerResponse<S, B> impl<S, B> Future for LoggerResponse<S, B>
where where
B: MessageBody, B: MessageBody,
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
{ {
type Output = Result<ServiceResponse<StreamLog<B>>, Error>; type Output = Result<ServiceResponse<StreamLog<B>>, Error>;

View File

@ -91,16 +91,15 @@ impl NormalizePath {
} }
} }
impl<S, B> Transform<S> for NormalizePath impl<S, B> Transform<S, ServiceRequest> for NormalizePath
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type InitError = ();
type Transform = NormalizePathNormalization<S>; type Transform = NormalizePathNormalization<S>;
type InitError = ();
type Future = Ready<Result<Self::Transform, Self::InitError>>; type Future = Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
@ -119,12 +118,11 @@ pub struct NormalizePathNormalization<S> {
trailing_slash_behavior: TrailingSlash, trailing_slash_behavior: TrailingSlash,
} }
impl<S, B> Service for NormalizePathNormalization<S> impl<S, B> Service<ServiceRequest> for NormalizePathNormalization<S>
where where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>, S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static, S::Future: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse<B>; type Response = ServiceResponse<B>;
type Error = Error; type Error = Error;
type Future = S::Future; type Future = S::Future;

View File

@ -9,7 +9,8 @@ use actix_http::{Error, Extensions, Response};
use actix_router::IntoPattern; use actix_router::IntoPattern;
use actix_service::boxed::{self, BoxService, BoxServiceFactory}; use actix_service::boxed::{self, BoxService, BoxServiceFactory};
use actix_service::{ use actix_service::{
apply, apply_fn_factory, IntoServiceFactory, Service, ServiceFactory, Transform, apply, apply_fn_factory, IntoServiceFactory, Service, ServiceFactory,
ServiceFactoryExt, Transform,
}; };
use futures_core::future::LocalBoxFuture; use futures_core::future::LocalBoxFuture;
@ -78,8 +79,8 @@ impl Resource {
impl<T> Resource<T> impl<T> Resource<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -250,8 +251,8 @@ where
mw: M, mw: M,
) -> Resource< ) -> Resource<
impl ServiceFactory< impl ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -260,7 +261,7 @@ where
where where
M: Transform< M: Transform<
T::Service, T::Service,
Request = ServiceRequest, ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -317,8 +318,8 @@ where
mw: F, mw: F,
) -> Resource< ) -> Resource<
impl ServiceFactory< impl ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -345,10 +346,10 @@ where
/// default handler from `App` or `Scope`. /// default handler from `App` or `Scope`.
pub fn default_service<F, U>(mut self, f: F) -> Self pub fn default_service<F, U>(mut self, f: F) -> Self
where where
F: IntoServiceFactory<U>, F: IntoServiceFactory<U, ServiceRequest>,
U: ServiceFactory< U: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
> + 'static, > + 'static,
@ -368,8 +369,8 @@ where
impl<T> HttpServiceFactory for Resource<T> impl<T> HttpServiceFactory for Resource<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -398,11 +399,11 @@ where
} }
} }
impl<T> IntoServiceFactory<T> for Resource<T> impl<T> IntoServiceFactory<T, ServiceRequest> for Resource<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -425,13 +426,12 @@ pub struct ResourceFactory {
default: Rc<RefCell<Option<Rc<HttpNewService>>>>, default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
} }
impl ServiceFactory for ResourceFactory { impl ServiceFactory<ServiceRequest> for ResourceFactory {
type Config = ();
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type InitError = (); type Config = ();
type Service = ResourceService; type Service = ResourceService;
type InitError = ();
type Future = CreateResourceService; type Future = CreateResourceService;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {
@ -520,8 +520,7 @@ pub struct ResourceService {
default: Option<HttpService>, default: Option<HttpService>,
} }
impl Service for ResourceService { impl Service<ServiceRequest> for ResourceService {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = LocalBoxFuture<'static, Result<ServiceResponse, Error>>; type Future = LocalBoxFuture<'static, Result<ServiceResponse, Error>>;
@ -567,9 +566,8 @@ impl ResourceEndpoint {
} }
} }
impl ServiceFactory for ResourceEndpoint { impl ServiceFactory<ServiceRequest> for ResourceEndpoint {
type Config = (); type Config = ();
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
@ -585,7 +583,7 @@ impl ServiceFactory for ResourceEndpoint {
mod tests { mod tests {
use std::time::Duration; use std::time::Duration;
use actix_rt::time::delay_for; use actix_rt::time::sleep;
use actix_service::Service; use actix_service::Service;
use futures_util::future::ok; use futures_util::future::ok;
@ -653,7 +651,7 @@ mod tests {
async fn test_to() { async fn test_to() {
let mut srv = let mut srv =
init_service(App::new().service(web::resource("/test").to(|| async { init_service(App::new().service(web::resource("/test").to(|| async {
delay_for(Duration::from_millis(100)).await; sleep(Duration::from_millis(100)).await;
Ok::<_, Error>(HttpResponse::Ok()) Ok::<_, Error>(HttpResponse::Ok())
}))) })))
.await; .await;

View File

@ -18,7 +18,7 @@ use crate::HttpResponse;
type BoxedRouteService = Box< type BoxedRouteService = Box<
dyn Service< dyn Service<
Request = ServiceRequest, ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
Future = LocalBoxFuture<'static, Result<ServiceResponse, Error>>, Future = LocalBoxFuture<'static, Result<ServiceResponse, Error>>,
@ -27,8 +27,8 @@ type BoxedRouteService = Box<
type BoxedRouteNewService = Box< type BoxedRouteNewService = Box<
dyn ServiceFactory< dyn ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -63,9 +63,8 @@ impl Route {
} }
} }
impl ServiceFactory for Route { impl ServiceFactory<ServiceRequest> for Route {
type Config = (); type Config = ();
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
@ -117,8 +116,7 @@ impl RouteService {
} }
} }
impl Service for RouteService { impl Service<ServiceRequest> for RouteService {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
@ -233,7 +231,7 @@ impl Route {
struct RouteNewService<T> struct RouteNewService<T>
where where
T: ServiceFactory<Request = ServiceRequest, Error = Error>, T: ServiceFactory<ServiceRequest, Error = Error>,
{ {
service: T, service: T,
} }
@ -241,33 +239,32 @@ where
impl<T> RouteNewService<T> impl<T> RouteNewService<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
>, >,
T::Future: 'static, T::Future: 'static,
T::Service: 'static, T::Service: 'static,
<T::Service as Service>::Future: 'static, <T::Service as Service<ServiceRequest>>::Future: 'static,
{ {
pub fn new(service: T) -> Self { pub fn new(service: T) -> Self {
RouteNewService { service } RouteNewService { service }
} }
} }
impl<T> ServiceFactory for RouteNewService<T> impl<T> ServiceFactory<ServiceRequest> for RouteNewService<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
>, >,
T::Future: 'static, T::Future: 'static,
T::Service: 'static, T::Service: 'static,
<T::Service as Service>::Future: 'static, <T::Service as Service<ServiceRequest>>::Future: 'static,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Config = (); type Config = ();
@ -289,16 +286,15 @@ where
} }
} }
struct RouteServiceWrapper<T: Service> { struct RouteServiceWrapper<T: Service<ServiceRequest>> {
service: T, service: T,
} }
impl<T> Service for RouteServiceWrapper<T> impl<T> Service<ServiceRequest> for RouteServiceWrapper<T>
where where
T::Future: 'static, T::Future: 'static,
T: Service<Request = ServiceRequest, Response = ServiceResponse, Error = Error>, T: Service<ServiceRequest, Response = ServiceResponse, Error = Error>,
{ {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
@ -316,7 +312,7 @@ where
mod tests { mod tests {
use std::time::Duration; use std::time::Duration;
use actix_rt::time::delay_for; use actix_rt::time::sleep;
use bytes::Bytes; use bytes::Bytes;
use serde_derive::Serialize; use serde_derive::Serialize;
@ -340,16 +336,16 @@ mod tests {
Err::<HttpResponse, _>(error::ErrorBadRequest("err")) Err::<HttpResponse, _>(error::ErrorBadRequest("err"))
})) }))
.route(web::post().to(|| async { .route(web::post().to(|| async {
delay_for(Duration::from_millis(100)).await; sleep(Duration::from_millis(100)).await;
Ok::<_, ()>(HttpResponse::Created()) Ok::<_, ()>(HttpResponse::Created())
})) }))
.route(web::delete().to(|| async { .route(web::delete().to(|| async {
delay_for(Duration::from_millis(100)).await; sleep(Duration::from_millis(100)).await;
Err::<HttpResponse, _>(error::ErrorBadRequest("err")) Err::<HttpResponse, _>(error::ErrorBadRequest("err"))
})), })),
) )
.service(web::resource("/json").route(web::get().to(|| async { .service(web::resource("/json").route(web::get().to(|| async {
delay_for(Duration::from_millis(25)).await; sleep(Duration::from_millis(25)).await;
web::Json(MyObject { web::Json(MyObject {
name: "test".to_string(), name: "test".to_string(),
}) })

View File

@ -9,7 +9,8 @@ use actix_http::{Extensions, Response};
use actix_router::{ResourceDef, ResourceInfo, Router}; use actix_router::{ResourceDef, ResourceInfo, Router};
use actix_service::boxed::{self, BoxService, BoxServiceFactory}; use actix_service::boxed::{self, BoxService, BoxServiceFactory};
use actix_service::{ use actix_service::{
apply, apply_fn_factory, IntoServiceFactory, Service, ServiceFactory, Transform, apply, apply_fn_factory, IntoServiceFactory, Service, ServiceFactory,
ServiceFactoryExt, Transform,
}; };
use futures_core::future::LocalBoxFuture; use futures_core::future::LocalBoxFuture;
@ -88,8 +89,8 @@ impl Scope {
impl<T> Scope<T> impl<T> Scope<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -284,10 +285,10 @@ where
/// If default resource is not registered, app's default resource is being used. /// If default resource is not registered, app's default resource is being used.
pub fn default_service<F, U>(mut self, f: F) -> Self pub fn default_service<F, U>(mut self, f: F) -> Self
where where
F: IntoServiceFactory<U>, F: IntoServiceFactory<U, ServiceRequest>,
U: ServiceFactory< U: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
> + 'static, > + 'static,
@ -317,8 +318,8 @@ where
mw: M, mw: M,
) -> Scope< ) -> Scope<
impl ServiceFactory< impl ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -327,7 +328,7 @@ where
where where
M: Transform< M: Transform<
T::Service, T::Service,
Request = ServiceRequest, ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -382,8 +383,8 @@ where
mw: F, mw: F,
) -> Scope< ) -> Scope<
impl ServiceFactory< impl ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -409,8 +410,8 @@ where
impl<T> HttpServiceFactory for Scope<T> impl<T> HttpServiceFactory for Scope<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -480,9 +481,8 @@ pub struct ScopeFactory {
default: Rc<RefCell<Option<Rc<HttpNewService>>>>, default: Rc<RefCell<Option<Rc<HttpNewService>>>>,
} }
impl ServiceFactory for ScopeFactory { impl ServiceFactory<ServiceRequest> for ScopeFactory {
type Config = (); type Config = ();
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type InitError = (); type InitError = ();
@ -601,8 +601,7 @@ pub struct ScopeService {
_ready: Option<(ServiceRequest, ResourceInfo)>, _ready: Option<(ServiceRequest, ResourceInfo)>,
} }
impl Service for ScopeService { impl Service<ServiceRequest> for ScopeService {
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
@ -653,13 +652,12 @@ impl ScopeEndpoint {
} }
} }
impl ServiceFactory for ScopeEndpoint { impl ServiceFactory<ServiceRequest> for ScopeEndpoint {
type Config = ();
type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type InitError = (); type Config = ();
type Service = ScopeService; type Service = ScopeService;
type InitError = ();
type Future = ScopeFactoryResponse; type Future = ScopeFactoryResponse;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future {

View File

@ -20,9 +20,9 @@ use actix_service::pipeline_factory;
use futures_util::future::ok; use futures_util::future::ok;
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
use actix_tls::openssl::{AlpnError, SslAcceptor, SslAcceptorBuilder}; use actix_tls::accept::openssl::{AlpnError, SslAcceptor, SslAcceptorBuilder};
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
use actix_tls::rustls::ServerConfig as RustlsServerConfig; use actix_tls::accept::rustls::ServerConfig as RustlsServerConfig;
use crate::config::AppConfig; use crate::config::AppConfig;
@ -58,8 +58,8 @@ struct Config {
pub struct HttpServer<F, I, S, B> pub struct HttpServer<F, I, S, B>
where where
F: Fn() -> I + Send + Clone + 'static, F: Fn() -> I + Send + Clone + 'static,
I: IntoServiceFactory<S>, I: IntoServiceFactory<S, Request>,
S: ServiceFactory<Config = AppConfig, Request = Request>, S: ServiceFactory<Request, Config = AppConfig>,
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>>,
@ -67,7 +67,7 @@ where
{ {
pub(super) factory: F, pub(super) factory: F,
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
backlog: i32, backlog: u32,
sockets: Vec<Socket>, sockets: Vec<Socket>,
builder: ServerBuilder, builder: ServerBuilder,
on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>, on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>,
@ -77,12 +77,13 @@ where
impl<F, I, S, B> HttpServer<F, I, S, B> impl<F, I, S, B> HttpServer<F, I, S, B>
where where
F: Fn() -> I + Send + Clone + 'static, F: Fn() -> I + Send + Clone + 'static,
I: IntoServiceFactory<S>, I: IntoServiceFactory<S, Request>,
S: ServiceFactory<Config = AppConfig, Request = Request>, S: ServiceFactory<Request, Config = AppConfig> + 'static,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static, S::Response: Into<Response<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
S::Service: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
/// Create new http server with application factory /// Create new http server with application factory
@ -147,7 +148,7 @@ where
/// Generally set in the 64-2048 range. Default value is 2048. /// Generally set in the 64-2048 range. Default value is 2048.
/// ///
/// This method should be called before `bind()` method call. /// This method should be called before `bind()` method call.
pub fn backlog(mut self, backlog: i32) -> Self { pub fn backlog(mut self, backlog: u32) -> Self {
self.backlog = backlog; self.backlog = backlog;
self.builder = self.builder.backlog(backlog); self.builder = self.builder.backlog(backlog);
self self
@ -170,8 +171,10 @@ where
/// limit the global TLS CPU usage. /// limit the global TLS CPU usage.
/// ///
/// By default max connections is set to a 256. /// By default max connections is set to a 256.
#[allow(unused_variables)]
pub fn max_connection_rate(self, num: usize) -> Self { pub fn max_connection_rate(self, num: usize) -> Self {
actix_tls::max_concurrent_tls_connect(num); #[cfg(any(feature = "rustls", feature = "openssl"))]
actix_tls::accept::max_concurrent_tls_connect(num);
self self
} }
@ -603,8 +606,8 @@ where
impl<F, I, S, B> HttpServer<F, I, S, B> impl<F, I, S, B> HttpServer<F, I, S, B>
where where
F: Fn() -> I + Send + Clone + 'static, F: Fn() -> I + Send + Clone + 'static,
I: IntoServiceFactory<S>, I: IntoServiceFactory<S, Request>,
S: ServiceFactory<Config = AppConfig, Request = Request>, S: ServiceFactory<Request, Config = AppConfig>,
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>>,
@ -639,7 +642,7 @@ where
fn create_tcp_listener( fn create_tcp_listener(
addr: net::SocketAddr, addr: net::SocketAddr,
backlog: i32, backlog: u32,
) -> io::Result<net::TcpListener> { ) -> io::Result<net::TcpListener> {
use socket2::{Domain, Protocol, Socket, Type}; use socket2::{Domain, Protocol, Socket, Type};
let domain = match addr { let domain = match addr {
@ -649,6 +652,8 @@ fn create_tcp_listener(
let socket = Socket::new(domain, Type::stream(), Some(Protocol::tcp()))?; let socket = Socket::new(domain, Type::stream(), Some(Protocol::tcp()))?;
socket.set_reuse_address(true)?; socket.set_reuse_address(true)?;
socket.bind(&addr.into())?; socket.bind(&addr.into())?;
// clamp backlog to max u32 that fits in i32 range
let backlog = backlog.min(i32::MAX as u32) as i32;
socket.listen(backlog)?; socket.listen(backlog)?;
Ok(socket.into_tcp_listener()) Ok(socket.into_tcp_listener())
} }

View File

@ -486,10 +486,10 @@ impl WebService {
/// Set a service factory implementation and generate web service. /// Set a service factory implementation and generate web service.
pub fn finish<T, F>(self, service: F) -> impl HttpServiceFactory pub fn finish<T, F>(self, service: F) -> impl HttpServiceFactory
where where
F: IntoServiceFactory<T>, F: IntoServiceFactory<T, ServiceRequest>,
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),
@ -514,8 +514,8 @@ struct WebServiceImpl<T> {
impl<T> HttpServiceFactory for WebServiceImpl<T> impl<T> HttpServiceFactory for WebServiceImpl<T>
where where
T: ServiceFactory< T: ServiceFactory<
ServiceRequest,
Config = (), Config = (),
Request = ServiceRequest,
Response = ServiceResponse, Response = ServiceResponse,
Error = Error, Error = Error,
InitError = (), InitError = (),

View File

@ -11,7 +11,7 @@ use actix_http::http::{Error as HttpError, Method, StatusCode, Uri, Version};
use actix_http::test::TestRequest as HttpTestRequest; use actix_http::test::TestRequest as HttpTestRequest;
use actix_http::{cookie::Cookie, ws, Extensions, HttpService, Request}; use actix_http::{cookie::Cookie, ws, Extensions, HttpService, Request};
use actix_router::{Path, ResourceDef, Url}; use actix_router::{Path, ResourceDef, Url};
use actix_rt::{time::delay_for, System}; use actix_rt::{time::sleep, System};
use actix_service::{ use actix_service::{
map_config, IntoService, IntoServiceFactory, Service, ServiceFactory, map_config, IntoService, IntoServiceFactory, Service, ServiceFactory,
}; };
@ -37,16 +37,14 @@ use crate::{Error, HttpRequest, HttpResponse};
/// Create service that always responds with `HttpResponse::Ok()` /// Create service that always responds with `HttpResponse::Ok()`
pub fn ok_service( pub fn ok_service(
) -> impl Service<Request = ServiceRequest, Response = ServiceResponse<Body>, Error = Error> ) -> impl Service<ServiceRequest, Response = ServiceResponse<Body>, Error = Error> {
{
default_service(StatusCode::OK) default_service(StatusCode::OK)
} }
/// Create service that responds with response with specified status code /// Create service that responds with response with specified status code
pub fn default_service( pub fn default_service(
status_code: StatusCode, status_code: StatusCode,
) -> impl Service<Request = ServiceRequest, Response = ServiceResponse<Body>, Error = Error> ) -> impl Service<ServiceRequest, Response = ServiceResponse<Body>, Error = Error> {
{
(move |req: ServiceRequest| { (move |req: ServiceRequest| {
ok(req.into_response(HttpResponse::build(status_code).finish())) ok(req.into_response(HttpResponse::build(status_code).finish()))
}) })
@ -77,12 +75,12 @@ pub fn default_service(
/// ``` /// ```
pub async fn init_service<R, S, B, E>( pub async fn init_service<R, S, B, E>(
app: R, app: R,
) -> impl Service<Request = Request, Response = ServiceResponse<B>, Error = E> ) -> impl Service<Request, Response = ServiceResponse<B>, Error = E>
where where
R: IntoServiceFactory<S>, R: IntoServiceFactory<S, Request>,
S: ServiceFactory< S: ServiceFactory<
Request,
Config = AppConfig, Config = AppConfig,
Request = Request,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = E, Error = E,
>, >,
@ -96,15 +94,12 @@ where
/// Fallible version of init_service that allows testing data factory errors. /// Fallible version of init_service that allows testing data factory errors.
pub(crate) async fn try_init_service<R, S, B, E>( pub(crate) async fn try_init_service<R, S, B, E>(
app: R, app: R,
) -> Result< ) -> Result<impl Service<Request, Response = ServiceResponse<B>, Error = E>, S::InitError>
impl Service<Request = Request, Response = ServiceResponse<B>, Error = E>,
S::InitError,
>
where where
R: IntoServiceFactory<S>, R: IntoServiceFactory<S, Request>,
S: ServiceFactory< S: ServiceFactory<
Request,
Config = AppConfig, Config = AppConfig,
Request = Request,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = E, Error = E,
>, >,
@ -138,7 +133,7 @@ where
/// ``` /// ```
pub async fn call_service<S, R, B, E>(app: &mut S, req: R) -> S::Response pub async fn call_service<S, R, B, E>(app: &mut S, req: R) -> S::Response
where where
S: Service<Request = R, Response = ServiceResponse<B>, Error = E>, S: Service<R, Response = ServiceResponse<B>, Error = E>,
E: std::fmt::Debug, E: std::fmt::Debug,
{ {
app.call(req).await.unwrap() app.call(req).await.unwrap()
@ -171,7 +166,7 @@ where
/// ``` /// ```
pub async fn read_response<S, B>(app: &mut S, req: Request) -> Bytes pub async fn read_response<S, B>(app: &mut S, req: Request) -> Bytes
where where
S: Service<Request = Request, Response = ServiceResponse<B>, Error = Error>, S: Service<Request, Response = ServiceResponse<B>, Error = Error>,
B: MessageBody + Unpin, B: MessageBody + Unpin,
{ {
let mut resp = app let mut resp = app
@ -321,7 +316,7 @@ where
/// ``` /// ```
pub async fn read_response_json<S, B, T>(app: &mut S, req: Request) -> T pub async fn read_response_json<S, B, T>(app: &mut S, req: Request) -> T
where where
S: Service<Request = Request, Response = ServiceResponse<B>, Error = Error>, S: Service<Request, Response = ServiceResponse<B>, Error = Error>,
B: MessageBody + Unpin, B: MessageBody + Unpin,
T: DeserializeOwned, T: DeserializeOwned,
{ {
@ -602,7 +597,7 @@ impl TestRequest {
/// Complete request creation, calls service and waits for response future completion. /// Complete request creation, calls service and waits for response future completion.
pub async fn send_request<S, B, E>(self, app: &mut S) -> S::Response pub async fn send_request<S, B, E>(self, app: &mut S) -> S::Response
where where
S: Service<Request = Request, Response = ServiceResponse<B>, Error = E>, S: Service<Request, Response = ServiceResponse<B>, Error = E>,
E: std::fmt::Debug, E: std::fmt::Debug,
{ {
let req = self.to_request(); let req = self.to_request();
@ -639,12 +634,12 @@ impl TestRequest {
pub fn start<F, I, S, B>(factory: F) -> TestServer pub fn start<F, I, S, B>(factory: F) -> TestServer
where where
F: Fn() -> I + Send + Clone + 'static, F: Fn() -> I + Send + Clone + 'static,
I: IntoServiceFactory<S>, I: IntoServiceFactory<S, Request>,
S: ServiceFactory<Config = AppConfig, Request = Request> + 'static, S: ServiceFactory<Request, Config = AppConfig> + 'static,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<HttpResponse<B>> + 'static, S::Response: Into<HttpResponse<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
start_with(TestServerConfig::default(), factory) start_with(TestServerConfig::default(), factory)
@ -678,12 +673,12 @@ where
pub fn start_with<F, I, S, B>(cfg: TestServerConfig, factory: F) -> TestServer pub fn start_with<F, I, S, B>(cfg: TestServerConfig, factory: F) -> TestServer
where where
F: Fn() -> I + Send + Clone + 'static, F: Fn() -> I + Send + Clone + 'static,
I: IntoServiceFactory<S>, I: IntoServiceFactory<S, Request>,
S: ServiceFactory<Config = AppConfig, Request = Request> + 'static, S: ServiceFactory<Request, Config = AppConfig> + 'static,
S::Error: Into<Error> + 'static, S::Error: Into<Error> + 'static,
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<HttpResponse<B>> + 'static, S::Response: Into<HttpResponse<B>> + 'static,
<S::Service as Service>::Future: 'static, <S::Service as Service<Request>>::Future: 'static,
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
@ -788,10 +783,13 @@ where
}), }),
}, },
} }
.unwrap() .unwrap();
.start();
sys.block_on(async {
let srv = srv.start();
tx.send((System::current(), srv, local_addr)).unwrap();
});
tx.send((System::current(), srv, local_addr)).unwrap();
sys.run() sys.run()
}); });
@ -1022,7 +1020,7 @@ impl TestServer {
pub async fn stop(self) { pub async fn stop(self) {
self.server.stop(true).await; self.server.stop(true).await;
self.system.stop(); self.system.stop();
delay_for(time::Duration::from_millis(100)).await; sleep(time::Duration::from_millis(100)).await;
} }
} }

View File

@ -367,7 +367,7 @@ where
let json = if let Ok(Some(mime)) = req.mime_type() { let json = if let Ok(Some(mime)) = req.mime_type() {
mime.subtype() == mime::JSON mime.subtype() == mime::JSON
|| mime.suffix() == Some(mime::JSON) || mime.suffix() == Some(mime::JSON)
|| ctype.as_ref().map_or(false, |predicate| predicate(mime)) || ctype.map_or(false, |predicate| predicate(mime))
} else { } else {
false false
}; };

View File

@ -5,7 +5,6 @@ use std::future::Future;
pub use actix_http::Response as HttpResponse; pub use actix_http::Response as HttpResponse;
pub use bytes::{Buf, BufMut, Bytes, BytesMut}; pub use bytes::{Buf, BufMut, Bytes, BytesMut};
pub use futures_channel::oneshot::Canceled;
use crate::error::BlockingError; use crate::error::BlockingError;
use crate::extract::FromRequest; use crate::extract::FromRequest;

View File

@ -15,26 +15,30 @@ async fn test_start() {
thread::spawn(move || { thread::spawn(move || {
let sys = actix_rt::System::new("test"); let sys = actix_rt::System::new("test");
let srv = HttpServer::new(|| { sys.block_on(async {
App::new().service( let srv = HttpServer::new(|| {
web::resource("/").route(web::to(|| HttpResponse::Ok().body("test"))), App::new().service(
) web::resource("/")
}) .route(web::to(|| HttpResponse::Ok().body("test"))),
.workers(1) )
.backlog(1) })
.max_connections(10) .workers(1)
.max_connection_rate(10) .backlog(1)
.keep_alive(10) .max_connections(10)
.client_timeout(5000) .max_connection_rate(10)
.client_shutdown(0) .keep_alive(10)
.server_hostname("localhost") .client_timeout(5000)
.system_exit() .client_shutdown(0)
.disable_signals() .server_hostname("localhost")
.bind(format!("{}", addr)) .system_exit()
.unwrap() .disable_signals()
.run(); .bind(format!("{}", addr))
.unwrap()
.run();
let _ = tx.send((srv, actix_rt::System::current()));
});
let _ = tx.send((srv, actix_rt::System::current()));
let _ = sys.run(); let _ = sys.run();
}); });
let (srv, sys) = rx.recv().unwrap(); let (srv, sys) = rx.recv().unwrap();
@ -101,10 +105,13 @@ async fn test_start_ssl() {
.system_exit() .system_exit()
.disable_signals() .disable_signals()
.bind_openssl(format!("{}", addr), builder) .bind_openssl(format!("{}", addr), builder)
.unwrap() .unwrap();
.run();
sys.block_on(async {
let srv = srv.run();
let _ = tx.send((srv, actix_rt::System::current()));
});
let _ = tx.send((srv, actix_rt::System::current()));
let _ = sys.run(); let _ = sys.run();
}); });
let (srv, sys) = rx.recv().unwrap(); let (srv, sys) = rx.recv().unwrap();

View File

@ -45,7 +45,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
struct TestBody { struct TestBody {
data: Bytes, data: Bytes,
chunk_size: usize, chunk_size: usize,
delay: actix_rt::time::Delay, delay: Pin<Box<actix_rt::time::Sleep>>,
} }
impl TestBody { impl TestBody {
@ -53,7 +53,7 @@ impl TestBody {
TestBody { TestBody {
data, data,
chunk_size, chunk_size,
delay: actix_rt::time::delay_for(std::time::Duration::from_millis(10)), delay: Box::pin(actix_rt::time::sleep(std::time::Duration::from_millis(10))),
} }
} }
} }
@ -67,7 +67,8 @@ impl futures_core::stream::Stream for TestBody {
) -> Poll<Option<Self::Item>> { ) -> Poll<Option<Self::Item>> {
ready!(Pin::new(&mut self.delay).poll(cx)); ready!(Pin::new(&mut self.delay).poll(cx));
self.delay = actix_rt::time::delay_for(std::time::Duration::from_millis(10)); self.delay =
Box::pin(actix_rt::time::sleep(std::time::Duration::from_millis(10)));
let chunk_size = std::cmp::min(self.chunk_size, self.data.len()); let chunk_size = std::cmp::min(self.chunk_size, self.data.len());
let chunk = self.data.split_to(chunk_size); let chunk = self.data.split_to(chunk_size);
if chunk.is_empty() { if chunk.is_empty() {