diff --git a/Cargo.toml b/Cargo.toml index 88a9ba88f..f41147819 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,12 +37,10 @@ session = ["cookie/secure"] ssl = ["openssl", "actix-connector/ssl"] [dependencies] -actix-service = "0.1.6" +actix-service = "0.2.0" actix-codec = "0.1.0" -# actix-connector = "0.1.0" -# actix-utils = "0.1.0" -actix-connector = { git = "https://github.com/actix/actix-net.git" } -actix-utils = { git = "https://github.com/actix/actix-net.git" } +actix-connector = "0.2.0" +actix-utils = "0.2.0" base64 = "0.10" backtrace = "0.3" @@ -78,7 +76,7 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-rt = "0.1.0" actix-web = "0.7" -actix-server = "0.1" +actix-server = "0.2" actix-http-test = { path="test-server" } env_logger = "0.6" serde_derive = "1.0" diff --git a/src/client/connector.rs b/src/client/connector.rs index 05e24e51c..fea9b9c0a 100644 --- a/src/client/connector.rs +++ b/src/client/connector.rs @@ -135,8 +135,11 @@ impl Connector { /// Finish configuration process and create connector service. pub fn service( self, - ) -> impl Service + Clone - { + ) -> impl Service< + Request = Connect, + Response = impl Connection, + Error = ConnectorError, + > + Clone { #[cfg(not(feature = "ssl"))] { let connector = TimeoutService::new( @@ -237,7 +240,11 @@ mod connect_impl { pub(crate) struct InnerConnector where Io: AsyncRead + AsyncWrite + 'static, - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io, Protocol), + Error = ConnectorError, + >, { pub(crate) tcp_pool: ConnectionPool, } @@ -245,8 +252,11 @@ mod connect_impl { impl Clone for InnerConnector where Io: AsyncRead + AsyncWrite + 'static, - T: Service - + Clone, + T: Service< + Request = Connect, + Response = (Connect, Io, Protocol), + Error = ConnectorError, + > + Clone, { fn clone(&self) -> Self { InnerConnector { @@ -255,15 +265,20 @@ mod connect_impl { } } - impl Service for InnerConnector + impl Service for InnerConnector where Io: AsyncRead + AsyncWrite + 'static, - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io, Protocol), + Error = ConnectorError, + >, { + type Request = Connect; type Response = IoConnection; type Error = ConnectorError; type Future = Either< - as Service>::Future, + as Service>::Future, FutureResult, ConnectorError>, >; @@ -298,12 +313,12 @@ mod connect_impl { Io1: AsyncRead + AsyncWrite + 'static, Io2: AsyncRead + AsyncWrite + 'static, T1: Service< - Connect, + Request = Connect, Response = (Connect, Io1, Protocol), Error = ConnectorError, >, T2: Service< - Connect, + Request = Connect, Response = (Connect, Io2, Protocol), Error = ConnectorError, >, @@ -317,12 +332,12 @@ mod connect_impl { Io1: AsyncRead + AsyncWrite + 'static, Io2: AsyncRead + AsyncWrite + 'static, T1: Service< - Connect, + Request = Connect, Response = (Connect, Io1, Protocol), Error = ConnectorError, > + Clone, T2: Service< - Connect, + Request = Connect, Response = (Connect, Io2, Protocol), Error = ConnectorError, > + Clone, @@ -335,21 +350,22 @@ mod connect_impl { } } - impl Service for InnerConnector + impl Service for InnerConnector where Io1: AsyncRead + AsyncWrite + 'static, Io2: AsyncRead + AsyncWrite + 'static, T1: Service< - Connect, + Request = Connect, Response = (Connect, Io1, Protocol), Error = ConnectorError, >, T2: Service< - Connect, + Request = Connect, Response = (Connect, Io2, Protocol), Error = ConnectorError, >, { + type Request = Connect; type Response = EitherConnection; type Error = ConnectorError; type Future = Either< @@ -384,15 +400,23 @@ mod connect_impl { pub(crate) struct InnerConnectorResponseA where Io1: AsyncRead + AsyncWrite + 'static, - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io1, Protocol), + Error = ConnectorError, + >, { - fut: as Service>::Future, + fut: as Service>::Future, _t: PhantomData, } impl Future for InnerConnectorResponseA where - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io1, Protocol), + Error = ConnectorError, + >, Io1: AsyncRead + AsyncWrite + 'static, Io2: AsyncRead + AsyncWrite + 'static, { @@ -410,15 +434,23 @@ mod connect_impl { pub(crate) struct InnerConnectorResponseB where Io2: AsyncRead + AsyncWrite + 'static, - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io2, Protocol), + Error = ConnectorError, + >, { - fut: as Service>::Future, + fut: as Service>::Future, _t: PhantomData, } impl Future for InnerConnectorResponseB where - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io2, Protocol), + Error = ConnectorError, + >, Io1: AsyncRead + AsyncWrite + 'static, Io2: AsyncRead + AsyncWrite + 'static, { diff --git a/src/client/pool.rs b/src/client/pool.rs index 425e89395..188980cb3 100644 --- a/src/client/pool.rs +++ b/src/client/pool.rs @@ -48,7 +48,11 @@ pub(crate) struct ConnectionPool( impl ConnectionPool where Io: AsyncRead + AsyncWrite + 'static, - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io, Protocol), + Error = ConnectorError, + >, { pub(crate) fn new( connector: T, @@ -84,11 +88,16 @@ where } } -impl Service for ConnectionPool +impl Service for ConnectionPool where Io: AsyncRead + AsyncWrite + 'static, - T: Service, + T: Service< + Request = Connect, + Response = (Connect, Io, Protocol), + Error = ConnectorError, + >, { + type Request = Connect; type Response = IoConnection; type Error = ConnectorError; type Future = Either< diff --git a/src/client/request.rs b/src/client/request.rs index b62ebaf3c..b80f0e6dc 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -176,7 +176,7 @@ where ) -> impl Future where B: 'static, - T: Service, + T: Service, I: Connection, { let Self { head, body } = self; diff --git a/src/h1/dispatcher.rs b/src/h1/dispatcher.rs index f66955af1..7780223f2 100644 --- a/src/h1/dispatcher.rs +++ b/src/h1/dispatcher.rs @@ -35,14 +35,14 @@ bitflags! { } /// Dispatcher for HTTP/1.1 protocol -pub struct Dispatcher, B: MessageBody> +pub struct Dispatcher where S::Error: Debug, { inner: Option>, } -struct InnerDispatcher, B: MessageBody> +struct InnerDispatcher where S::Error: Debug, { @@ -66,13 +66,13 @@ enum DispatcherMessage { Error(Response<()>), } -enum State, B: MessageBody> { +enum State { None, ServiceCall(S::Future), SendPayload(ResponseBody), } -impl, B: MessageBody> State { +impl State { fn is_empty(&self) -> bool { if let State::None = self { true @@ -85,7 +85,7 @@ impl, B: MessageBody> State { impl Dispatcher where T: AsyncRead + AsyncWrite, - S: Service>, + S: Service>, S::Error: Debug, B: MessageBody, { @@ -139,7 +139,7 @@ where impl InnerDispatcher where T: AsyncRead + AsyncWrite, - S: Service>, + S: Service>, S::Error: Debug, B: MessageBody, { @@ -459,7 +459,7 @@ where impl Future for Dispatcher where T: AsyncRead + AsyncWrite, - S: Service>, + S: Service>, S::Error: Debug, B: MessageBody, { diff --git a/src/h1/service.rs b/src/h1/service.rs index d8f63a323..c35d18714 100644 --- a/src/h1/service.rs +++ b/src/h1/service.rs @@ -27,13 +27,13 @@ pub struct H1Service { impl H1Service where - S: NewService> + Clone, + S: NewService> + Clone, S::Service: Clone, S::Error: Debug, B: MessageBody, { /// Create new `HttpService` instance. - pub fn new>(service: F) -> Self { + pub fn new>(service: F) -> Self { let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0); H1Service { @@ -49,14 +49,15 @@ where } } -impl NewService for H1Service +impl NewService for H1Service where T: AsyncRead + AsyncWrite, - S: NewService> + Clone, + S: NewService> + Clone, S::Service: Clone, S::Error: Debug, B: MessageBody, { + type Request = T; type Response = H1ServiceResult; type Error = DispatchError; type InitError = S::InitError; @@ -88,7 +89,7 @@ pub struct H1ServiceBuilder { impl H1ServiceBuilder where - S: NewService, + S: NewService, S::Service: Clone, S::Error: Debug, { @@ -187,7 +188,7 @@ where pub fn finish(self, service: F) -> H1Service where B: MessageBody, - F: IntoNewService, + F: IntoNewService, { let cfg = ServiceConfig::new( self.keep_alive, @@ -203,7 +204,7 @@ where } #[doc(hidden)] -pub struct H1ServiceResponse, B> { +pub struct H1ServiceResponse { fut: S::Future, cfg: Option, _t: PhantomData<(T, B)>, @@ -212,7 +213,7 @@ pub struct H1ServiceResponse, B> { impl Future for H1ServiceResponse where T: AsyncRead + AsyncWrite, - S: NewService>, + S: NewService>, S::Service: Clone, S::Error: Debug, B: MessageBody, @@ -238,7 +239,7 @@ pub struct H1ServiceHandler { impl H1ServiceHandler where - S: Service> + Clone, + S: Service> + Clone, S::Error: Debug, B: MessageBody, { @@ -251,13 +252,14 @@ where } } -impl Service for H1ServiceHandler +impl Service for H1ServiceHandler where T: AsyncRead + AsyncWrite, - S: Service> + Clone, + S: Service> + Clone, S::Error: Debug, B: MessageBody, { + type Request = T; type Response = H1ServiceResult; type Error = DispatchError; type Future = Dispatcher; @@ -291,10 +293,11 @@ where } } -impl NewService for OneRequest +impl NewService for OneRequest where T: AsyncRead + AsyncWrite, { + type Request = T; type Response = (Request, Framed); type Error = ParseError; type InitError = (); @@ -316,10 +319,11 @@ pub struct OneRequestService { _t: PhantomData, } -impl Service for OneRequestService +impl Service for OneRequestService where T: AsyncRead + AsyncWrite, { + type Request = T; type Response = (Request, Framed); type Error = ParseError; type Future = OneRequestServiceResponse; diff --git a/src/h2/mod.rs b/src/h2/mod.rs new file mode 100644 index 000000000..4a54ec9fe --- /dev/null +++ b/src/h2/mod.rs @@ -0,0 +1,20 @@ +use std::fmt; + +mod service; + +/// H1 service response type +pub enum H2ServiceResult { + Disconnected, + Shutdown(T), +} + +impl fmt::Debug for H2ServiceResult { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + H2ServiceResult::Disconnected => write!(f, "H2ServiceResult::Disconnected"), + H2ServiceResult::Shutdown(ref v) => { + write!(f, "H2ServiceResult::Shutdown({:?})", v) + } + } + } +} diff --git a/src/h2/service.rs b/src/h2/service.rs new file mode 100644 index 000000000..827f84488 --- /dev/null +++ b/src/h2/service.rs @@ -0,0 +1,310 @@ +use std::fmt::Debug; +use std::marker::PhantomData; +use std::net; + +use actix_codec::{AsyncRead, AsyncWrite, Framed}; +use actix_service::{IntoNewService, NewService, Service}; +use bytes::Bytes; +use futures::future::{ok, FutureResult}; +use futures::{try_ready, Async, Future, Poll, Stream}; +use h2::server::{self, Connection, Handshake}; +use log::error; + +use crate::body::MessageBody; +use crate::config::{KeepAlive, ServiceConfig}; +use crate::error::{DispatchError, ParseError}; +use crate::request::Request; +use crate::response::Response; + +// use super::dispatcher::Dispatcher; +use super::H2ServiceResult; + +/// `NewService` implementation for HTTP2 transport +pub struct H2Service { + srv: S, + cfg: ServiceConfig, + _t: PhantomData<(T, B)>, +} + +impl H2Service +where + S: NewService> + Clone, + S::Service: Clone, + S::Error: Debug, + B: MessageBody, +{ + /// Create new `HttpService` instance. + pub fn new>(service: F) -> Self { + let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0); + + H2Service { + cfg, + srv: service.into_new_service(), + _t: PhantomData, + } + } + + /// Create builder for `HttpService` instance. + pub fn build() -> H2ServiceBuilder { + H2ServiceBuilder::new() + } +} + +impl NewService for H2Service +where + T: AsyncRead + AsyncWrite, + S: NewService> + Clone, + S::Service: Clone, + S::Error: Debug, + B: MessageBody, +{ + type Request = T; + type Response = H2ServiceResult; + type Error = (); //DispatchError; + type InitError = S::InitError; + type Service = H2ServiceHandler; + type Future = H2ServiceResponse; + + fn new_service(&self) -> Self::Future { + H2ServiceResponse { + fut: self.srv.new_service(), + cfg: Some(self.cfg.clone()), + _t: PhantomData, + } + } +} + +/// A http/2 new service builder +/// +/// This type can be used to construct an instance of `ServiceConfig` through a +/// builder-like pattern. +pub struct H2ServiceBuilder { + keep_alive: KeepAlive, + client_timeout: u64, + client_disconnect: u64, + host: String, + addr: net::SocketAddr, + secure: bool, + _t: PhantomData<(T, S)>, +} + +impl H2ServiceBuilder +where + S: NewService, + S::Service: Clone, + S::Error: Debug, +{ + /// Create instance of `H2ServiceBuilder` + pub fn new() -> H2ServiceBuilder { + H2ServiceBuilder { + keep_alive: KeepAlive::Timeout(5), + client_timeout: 5000, + client_disconnect: 0, + secure: false, + host: "localhost".to_owned(), + addr: "127.0.0.1:8080".parse().unwrap(), + _t: PhantomData, + } + } + + /// Enable secure flag for current server. + /// This flags also enables `client disconnect timeout`. + /// + /// By default this flag is set to false. + pub fn secure(mut self) -> Self { + self.secure = true; + if self.client_disconnect == 0 { + self.client_disconnect = 3000; + } + self + } + + /// Set server keep-alive setting. + /// + /// By default keep alive is set to a 5 seconds. + pub fn keep_alive>(mut self, val: U) -> Self { + self.keep_alive = val.into(); + self + } + + /// Set server client timeout in milliseconds for first request. + /// + /// Defines a timeout for reading client request header. If a client does not transmit + /// the entire set headers within this time, the request is terminated with + /// the 408 (Request Time-out) error. + /// + /// To disable timeout set value to 0. + /// + /// By default client timeout is set to 5000 milliseconds. + pub fn client_timeout(mut self, val: u64) -> Self { + self.client_timeout = val; + self + } + + /// Set server connection disconnect timeout in milliseconds. + /// + /// Defines a timeout for disconnect connection. If a disconnect procedure does not complete + /// within this time, the request get dropped. This timeout affects secure connections. + /// + /// To disable timeout set value to 0. + /// + /// By default disconnect timeout is set to 3000 milliseconds. + pub fn client_disconnect(mut self, val: u64) -> Self { + self.client_disconnect = val; + self + } + + /// Set server host name. + /// + /// Host name is used by application router aa a hostname for url + /// generation. Check [ConnectionInfo](./dev/struct.ConnectionInfo. + /// html#method.host) documentation for more information. + /// + /// By default host name is set to a "localhost" value. + pub fn server_hostname(mut self, val: &str) -> Self { + self.host = val.to_owned(); + self + } + + /// Set server ip address. + /// + /// Host name is used by application router aa a hostname for url + /// generation. Check [ConnectionInfo](./dev/struct.ConnectionInfo. + /// html#method.host) documentation for more information. + /// + /// By default server address is set to a "127.0.0.1:8080" + pub fn server_address(mut self, addr: U) -> Self { + match addr.to_socket_addrs() { + Err(err) => error!("Can not convert to SocketAddr: {}", err), + Ok(mut addrs) => { + if let Some(addr) = addrs.next() { + self.addr = addr; + } + } + } + self + } + + /// Finish service configuration and create `H1Service` instance. + pub fn finish(self, service: F) -> H2Service + where + B: MessageBody, + F: IntoNewService, + { + let cfg = ServiceConfig::new( + self.keep_alive, + self.client_timeout, + self.client_disconnect, + ); + H2Service { + cfg, + srv: service.into_new_service(), + _t: PhantomData, + } + } +} + +#[doc(hidden)] +pub struct H2ServiceResponse { + fut: S::Future, + cfg: Option, + _t: PhantomData<(T, B)>, +} + +impl Future for H2ServiceResponse +where + T: AsyncRead + AsyncWrite, + S: NewService>, + S::Service: Clone, + S::Error: Debug, + B: MessageBody, +{ + type Item = H2ServiceHandler; + type Error = S::InitError; + + fn poll(&mut self) -> Poll { + let service = try_ready!(self.fut.poll()); + Ok(Async::Ready(H2ServiceHandler::new( + self.cfg.take().unwrap(), + service, + ))) + } +} + +/// `Service` implementation for http/2 transport +pub struct H2ServiceHandler { + srv: S, + cfg: ServiceConfig, + _t: PhantomData<(T, B)>, +} + +impl H2ServiceHandler +where + S: Service> + Clone, + S::Error: Debug, + B: MessageBody, +{ + fn new(cfg: ServiceConfig, srv: S) -> H2ServiceHandler { + H2ServiceHandler { + srv, + cfg, + _t: PhantomData, + } + } +} + +impl Service for H2ServiceHandler +where + T: AsyncRead + AsyncWrite, + S: Service> + Clone, + S::Error: Debug, + B: MessageBody, +{ + type Request = T; + type Response = H2ServiceResult; + type Error = (); // DispatchError; + type Future = H2ServiceHandlerResponse; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + self.srv.poll_ready().map_err(|_| ()) + } + + fn call(&mut self, req: T) -> Self::Future { + H2ServiceHandlerResponse { + state: State::Handshake(server::handshake(req)), + _t: PhantomData, + } + } +} + +enum State { + Handshake(Handshake), + Connection(Connection), + Empty, +} + +pub struct H2ServiceHandlerResponse +where + T: AsyncRead + AsyncWrite, + S: Service> + Clone, + S::Error: Debug, + B: MessageBody, +{ + state: State, + _t: PhantomData, +} + +impl Future for H2ServiceHandlerResponse +where + T: AsyncRead + AsyncWrite, + S: Service> + Clone, + S::Error: Debug, + B: MessageBody, +{ + type Item = H2ServiceResult; + type Error = (); + + fn poll(&mut self) -> Poll { + unimplemented!() + } +} diff --git a/src/lib.rs b/src/lib.rs index 442637251..cdb4f0382 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,7 @@ mod service; pub mod error; pub mod h1; +pub mod h2; pub mod test; pub mod ws; diff --git a/src/service/senderror.rs b/src/service/senderror.rs index 57828187d..b469a61e6 100644 --- a/src/service/senderror.rs +++ b/src/service/senderror.rs @@ -22,11 +22,12 @@ where } } -impl NewService)>> for SendError +impl NewService for SendError where T: AsyncRead + AsyncWrite, E: ResponseError, { + type Request = Result)>; type Response = R; type Error = (E, Framed); type InitError = (); @@ -38,11 +39,12 @@ where } } -impl Service)>> for SendError +impl Service for SendError where T: AsyncRead + AsyncWrite, E: ResponseError, { + type Request = Result)>; type Response = R; type Error = (E, Framed); type Future = Either)>, SendErrorFut>; @@ -128,11 +130,12 @@ where } } -impl NewService<(Response, Framed)> for SendResponse +impl NewService for SendResponse where T: AsyncRead + AsyncWrite, B: MessageBody, { + type Request = (Response, Framed); type Response = Framed; type Error = Error; type InitError = (); @@ -144,11 +147,12 @@ where } } -impl Service<(Response, Framed)> for SendResponse +impl Service for SendResponse where T: AsyncRead + AsyncWrite, B: MessageBody, { + type Request = (Response, Framed); type Response = Framed; type Error = Error; type Future = SendResponseFut; diff --git a/src/ws/client/service.rs b/src/ws/client/service.rs index c48b6e0c1..586873d19 100644 --- a/src/ws/client/service.rs +++ b/src/ws/client/service.rs @@ -26,7 +26,7 @@ pub type DefaultClient = Client; /// WebSocket's client pub struct Client where - T: Service, + T: Service, T::Response: AsyncRead + AsyncWrite, { connector: T, @@ -34,7 +34,7 @@ where impl Client where - T: Service, + T: Service, T::Response: AsyncRead + AsyncWrite, { /// Create new websocket's client factory @@ -51,7 +51,7 @@ impl Default for Client { impl Clone for Client where - T: Service + Clone, + T: Service + Clone, T::Response: AsyncRead + AsyncWrite, { fn clone(&self) -> Self { @@ -61,12 +61,13 @@ where } } -impl Service for Client +impl Service for Client where - T: Service, + T: Service, T::Response: AsyncRead + AsyncWrite + 'static, T::Future: 'static, { + type Request = Connect; type Response = Framed; type Error = ClientError; type Future = Either< diff --git a/src/ws/frame.rs b/src/ws/frame.rs index 32ad4ef4f..d4c15627f 100644 --- a/src/ws/frame.rs +++ b/src/ws/frame.rs @@ -117,7 +117,7 @@ impl Parser { // control frames must have length <= 125 match opcode { OpCode::Ping | OpCode::Pong if length > 125 => { - return Err(ProtocolError::InvalidLength(length)) + return Err(ProtocolError::InvalidLength(length)); } OpCode::Close if length > 125 => { debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame."); diff --git a/src/ws/service.rs b/src/ws/service.rs index 8189b1955..137d41d43 100644 --- a/src/ws/service.rs +++ b/src/ws/service.rs @@ -20,7 +20,8 @@ impl Default for VerifyWebSockets { } } -impl NewService<(Request, Framed)> for VerifyWebSockets { +impl NewService for VerifyWebSockets { + type Request = (Request, Framed); type Response = (Request, Framed); type Error = (HandshakeError, Framed); type InitError = (); @@ -32,7 +33,8 @@ impl NewService<(Request, Framed)> for VerifyWebSockets { } } -impl Service<(Request, Framed)> for VerifyWebSockets { +impl Service for VerifyWebSockets { + type Request = (Request, Framed); type Response = (Request, Framed); type Error = (HandshakeError, Framed); type Future = FutureResult; diff --git a/src/ws/transport.rs b/src/ws/transport.rs index 6a4f4d227..da7782be5 100644 --- a/src/ws/transport.rs +++ b/src/ws/transport.rs @@ -7,7 +7,7 @@ use super::{Codec, Frame, Message}; pub struct Transport where - S: Service + 'static, + S: Service + 'static, T: AsyncRead + AsyncWrite, { inner: FramedTransport, @@ -16,17 +16,17 @@ where impl Transport where T: AsyncRead + AsyncWrite, - S: Service, + S: Service, S::Future: 'static, S::Error: 'static, { - pub fn new>(io: T, service: F) -> Self { + pub fn new>(io: T, service: F) -> Self { Transport { inner: FramedTransport::new(Framed::new(io, Codec::new()), service), } } - pub fn with>(framed: Framed, service: F) -> Self { + pub fn with>(framed: Framed, service: F) -> Self { Transport { inner: FramedTransport::new(framed, service), } @@ -36,7 +36,7 @@ where impl Future for Transport where T: AsyncRead + AsyncWrite, - S: Service, + S: Service, S::Future: 'static, S::Error: 'static, { diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 851b3efe4..81a3d909c 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -30,11 +30,11 @@ session = ["cookie/secure"] [dependencies] actix-codec = "0.1" -actix-service = "0.1.6" +actix-service = "0.2.0" actix-rt = "0.1.0" -actix-server = "0.1.0" +actix-server = "0.2.0" +actix-utils = "0.2.0" actix-http = { path=".." } -actix-utils = { git = "https://github.com/actix/actix-net.git" } base64 = "0.10" bytes = "0.4" diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index 1ef452044..8083ebb15 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -57,7 +57,8 @@ impl TestServer { pub fn with_factory( factory: F, ) -> TestServerRuntime< - impl Service + Clone, + impl Service + + Clone, > { let (tx, rx) = mpsc::channel(); @@ -89,8 +90,11 @@ impl TestServer { } fn new_connector( - ) -> impl Service + Clone - { + ) -> impl Service< + Request = Connect, + Response = impl Connection, + Error = ConnectorError, + > + Clone { #[cfg(feature = "ssl")] { use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode}; @@ -191,7 +195,7 @@ impl TestServerRuntime { impl TestServerRuntime where - T: Service + Clone, + T: Service + Clone, T::Response: Connection, { /// Connect to websocket server at a given path