1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-24 02:21:07 +01:00

add ServerConfig to server services

This commit is contained in:
Nikolay Kim 2019-03-09 07:27:56 -08:00
parent ac62e2dbf9
commit d2b96ff877
15 changed files with 163 additions and 45 deletions

View File

@ -20,6 +20,7 @@ members = [
"actix-rt", "actix-rt",
"actix-service", "actix-service",
"actix-server", "actix-server",
"actix-server-config",
"actix-test-server", "actix-test-server",
"actix-utils", "actix-utils",
"router", "router",

View File

@ -167,8 +167,8 @@ impl Connector {
/// Create new connector with custom resolver /// Create new connector with custom resolver
pub fn with_resolver( pub fn with_resolver(
resolver: Resolver<Connect>, resolver: Resolver<Connect>,
) -> impl Service<Connect, Response = (Connect, TcpStream), Error = ConnectorError> + Clone ) -> impl Service<Request = Connect, Response = (Connect, TcpStream), Error = ConnectorError>
{ + Clone {
Connector { resolver } Connector { resolver }
} }
@ -177,8 +177,8 @@ impl Connector {
cfg: ResolverConfig, cfg: ResolverConfig,
opts: ResolverOpts, opts: ResolverOpts,
) -> impl NewService< ) -> impl NewService<
Connect,
(), (),
Request = Connect,
Response = (Connect, TcpStream), Response = (Connect, TcpStream),
Error = ConnectorError, Error = ConnectorError,
InitError = E, InitError = E,
@ -195,7 +195,8 @@ impl Clone for Connector {
} }
} }
impl Service<Connect> for Connector { impl Service for Connector {
type Request = Connect;
type Response = (Connect, TcpStream); type Response = (Connect, TcpStream);
type Error = ConnectorError; type Error = ConnectorError;
type Future = Either<ConnectorFuture, ConnectorTcpFuture>; type Future = Either<ConnectorFuture, ConnectorTcpFuture>;
@ -272,7 +273,8 @@ impl<T: RequestPort> Default for TcpConnector<T> {
} }
} }
impl<T: RequestPort> Service<(T, VecDeque<IpAddr>)> for TcpConnector<T> { impl<T: RequestPort> Service for TcpConnector<T> {
type Request = (T, VecDeque<IpAddr>);
type Response = (T, TcpStream); type Response = (T, TcpStream);
type Error = io::Error; type Error = io::Error;
type Future = TcpConnectorResponse<T>; type Future = TcpConnectorResponse<T>;
@ -352,7 +354,8 @@ impl DefaultConnector {
} }
} }
impl Service<Connect> for DefaultConnector { impl Service for DefaultConnector {
type Request = Connect;
type Response = TcpStream; type Response = TcpStream;
type Error = ConnectorError; type Error = ConnectorError;
type Future = DefaultConnectorFuture; type Future = DefaultConnectorFuture;

View File

@ -67,7 +67,8 @@ impl<T> Clone for Resolver<T> {
} }
} }
impl<T: RequestHost> Service<T> for Resolver<T> { impl<T: RequestHost> Service for Resolver<T> {
type Request = T;
type Response = (T, VecDeque<IpAddr>); type Response = (T, VecDeque<IpAddr>);
type Error = ResolveError; type Error = ResolveError;
type Future = ResolverFuture<T>; type Future = ResolverFuture<T>;

View File

@ -26,7 +26,8 @@ impl<R, T, E> OpensslConnector<R, T, E> {
impl<R: RequestHost, T: AsyncRead + AsyncWrite> OpensslConnector<R, T, ()> { impl<R: RequestHost, T: AsyncRead + AsyncWrite> OpensslConnector<R, T, ()> {
pub fn service( pub fn service(
connector: SslConnector, connector: SslConnector,
) -> impl Service<(R, T), Response = (R, SslStream<T>), Error = HandshakeError<T>> { ) -> impl Service<Request = (R, T), Response = (R, SslStream<T>), Error = HandshakeError<T>>
{
OpensslConnectorService { OpensslConnectorService {
connector: connector, connector: connector,
_t: PhantomData, _t: PhantomData,
@ -43,9 +44,10 @@ impl<R, T, E> Clone for OpensslConnector<R, T, E> {
} }
} }
impl<R: RequestHost, T: AsyncRead + AsyncWrite, E> NewService<(R, T), ()> impl<R: RequestHost, T: AsyncRead + AsyncWrite, E> NewService<()>
for OpensslConnector<R, T, E> for OpensslConnector<R, T, E>
{ {
type Request = (R, T);
type Response = (R, SslStream<T>); type Response = (R, SslStream<T>);
type Error = HandshakeError<T>; type Error = HandshakeError<T>;
type Service = OpensslConnectorService<R, T>; type Service = OpensslConnectorService<R, T>;
@ -65,9 +67,8 @@ pub struct OpensslConnectorService<R, T> {
_t: PhantomData<(R, T)>, _t: PhantomData<(R, T)>,
} }
impl<R: RequestHost, T: AsyncRead + AsyncWrite> Service<(R, T)> impl<R: RequestHost, T: AsyncRead + AsyncWrite> Service for OpensslConnectorService<R, T> {
for OpensslConnectorService<R, T> type Request = (R, T);
{
type Response = (R, SslStream<T>); type Response = (R, SslStream<T>);
type Error = HandshakeError<T>; type Error = HandshakeError<T>;
type Future = ConnectAsyncExt<R, T>; type Future = ConnectAsyncExt<R, T>;

View File

@ -0,0 +1,18 @@
[package]
name = "actix-server-config"
version = "0.1.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix server config utils"
homepage = "https://actix.rs"
repository = "https://github.com/actix/actix-net.git"
license = "MIT/Apache-2.0"
edition = "2018"
workspace = ".."
[lib]
name = "actix_server_config"
path = "src/lib.rs"
[dependencies]
actix-service = { path="../actix-service" }
futures = "0.1.25"

View File

@ -0,0 +1,33 @@
use std::cell::Cell;
use std::net::SocketAddr;
use std::rc::Rc;
#[derive(Debug, Clone)]
pub struct ServerConfig {
addr: SocketAddr,
secure: Rc<Cell<bool>>,
}
impl ServerConfig {
pub fn new(addr: SocketAddr) -> Self {
ServerConfig {
addr,
secure: Rc::new(Cell::new(false)),
}
}
/// Returns the address of the local half of this TCP server socket
pub fn local_addr(&self) -> SocketAddr {
self.addr
}
/// Returns true if connection is secure (tls enabled)
pub fn secure(&self) -> bool {
self.secure.as_ref().get()
}
/// Set secure flag
pub fn set_secure(&self) {
self.secure.as_ref().set(true)
}
}

View File

@ -36,6 +36,7 @@ rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots"]
actix-rt = "0.2.0" actix-rt = "0.2.0"
#actix-service = "0.3.2" #actix-service = "0.3.2"
actix-service = { path="../actix-service" } actix-service = { path="../actix-service" }
actix-server-config = { path="../actix-server-config" }
log = "0.4" log = "0.4"
num_cpus = "1.0" num_cpus = "1.0"

View File

@ -150,14 +150,15 @@ impl ServerBuilder {
U: net::ToSocketAddrs, U: net::ToSocketAddrs,
{ {
let sockets = bind_addr(addr)?; let sockets = bind_addr(addr)?;
for lst in sockets {
let token = self.token.next(); let token = self.token.next();
self.services.push(StreamNewService::create( self.services.push(StreamNewService::create(
name.as_ref().to_string(), name.as_ref().to_string(),
token, token,
factory.clone(), factory.clone(),
lst.local_addr()?,
)); ));
for lst in sockets {
self.sockets.push((token, lst)); self.sockets.push((token, lst));
} }
Ok(self) Ok(self)
@ -178,6 +179,7 @@ impl ServerBuilder {
name.as_ref().to_string(), name.as_ref().to_string(),
token, token,
factory, factory,
lst.local_addr()?,
)); ));
self.sockets.push((token, lst)); self.sockets.push((token, lst));
Ok(self) Ok(self)

View File

@ -10,6 +10,8 @@ mod signals;
pub mod ssl; pub mod ssl;
mod worker; mod worker;
pub use actix_server_config::ServerConfig;
pub use self::builder::ServerBuilder; pub use self::builder::ServerBuilder;
pub use self::server::Server; pub use self::server::Server;
pub use self::service_config::{ServiceConfig, ServiceRuntime}; pub use self::service_config::{ServiceConfig, ServiceRuntime};

View File

@ -169,8 +169,8 @@ impl ServiceRuntime {
pub fn service<T, F>(&mut self, name: &str, service: F) pub fn service<T, F>(&mut self, name: &str, service: F)
where where
F: IntoNewService<T, TcpStream>, F: IntoNewService<T>,
T: NewService<TcpStream, Response = ()> + 'static, T: NewService<Request = TcpStream, Response = ()> + 'static,
T::Future: 'static, T::Future: 'static,
T::Service: 'static, T::Service: 'static,
T::InitError: fmt::Debug, T::InitError: fmt::Debug,
@ -191,7 +191,7 @@ impl ServiceRuntime {
type BoxedNewService = Box< type BoxedNewService = Box<
NewService< NewService<
(Option<CounterGuard>, ServerMessage), Request = (Option<CounterGuard>, ServerMessage),
Response = (), Response = (),
Error = (), Error = (),
InitError = (), InitError = (),
@ -204,14 +204,15 @@ struct ServiceFactory<T> {
inner: T, inner: T,
} }
impl<T> NewService<(Option<CounterGuard>, ServerMessage)> for ServiceFactory<T> impl<T> NewService for ServiceFactory<T>
where where
T: NewService<TcpStream, Response = ()>, T: NewService<Request = TcpStream, Response = ()>,
T::Future: 'static, T::Future: 'static,
T::Service: 'static, T::Service: 'static,
T::Error: 'static, T::Error: 'static,
T::InitError: fmt::Debug + 'static, T::InitError: fmt::Debug + 'static,
{ {
type Request = (Option<CounterGuard>, ServerMessage);
type Response = (); type Response = ();
type Error = (); type Error = ();
type InitError = (); type InitError = ();

View File

@ -1,7 +1,8 @@
use std::net::TcpStream; use std::net::{SocketAddr, TcpStream};
use std::time::Duration; use std::time::Duration;
use actix_rt::spawn; use actix_rt::spawn;
use actix_server_config::ServerConfig;
use actix_service::{NewService, Service}; use actix_service::{NewService, Service};
use futures::future::{err, ok, FutureResult}; use futures::future::{err, ok, FutureResult};
use futures::{Future, Poll}; use futures::{Future, Poll};
@ -23,7 +24,7 @@ pub(crate) enum ServerMessage {
} }
pub trait ServiceFactory: Send + Clone + 'static { pub trait ServiceFactory: Send + Clone + 'static {
type NewService: NewService<TokioTcpStream>; type NewService: NewService<ServerConfig, Request = TokioTcpStream>;
fn create(&self) -> Self::NewService; fn create(&self) -> Self::NewService;
} }
@ -38,7 +39,7 @@ pub(crate) trait InternalServiceFactory: Send {
pub(crate) type BoxedServerService = Box< pub(crate) type BoxedServerService = Box<
Service< Service<
(Option<CounterGuard>, ServerMessage), Request = (Option<CounterGuard>, ServerMessage),
Response = (), Response = (),
Error = (), Error = (),
Future = FutureResult<(), ()>, Future = FutureResult<(), ()>,
@ -55,12 +56,13 @@ impl<T> StreamService<T> {
} }
} }
impl<T> Service<(Option<CounterGuard>, ServerMessage)> for StreamService<T> impl<T> Service for StreamService<T>
where where
T: Service<TokioTcpStream>, T: Service<Request = TokioTcpStream>,
T::Future: 'static, T::Future: 'static,
T::Error: 'static, T::Error: 'static,
{ {
type Request = (Option<CounterGuard>, ServerMessage);
type Response = (); type Response = ();
type Error = (); type Error = ();
type Future = FutureResult<(), ()>; type Future = FutureResult<(), ()>;
@ -96,14 +98,25 @@ pub(crate) struct StreamNewService<F: ServiceFactory> {
name: String, name: String,
inner: F, inner: F,
token: Token, token: Token,
addr: SocketAddr,
} }
impl<F> StreamNewService<F> impl<F> StreamNewService<F>
where where
F: ServiceFactory, F: ServiceFactory,
{ {
pub(crate) fn create(name: String, token: Token, inner: F) -> Box<InternalServiceFactory> { pub(crate) fn create(
Box::new(Self { name, token, inner }) name: String,
token: Token,
inner: F,
addr: SocketAddr,
) -> Box<InternalServiceFactory> {
Box::new(Self {
name,
token,
inner,
addr,
})
} }
} }
@ -120,15 +133,17 @@ where
name: self.name.clone(), name: self.name.clone(),
inner: self.inner.clone(), inner: self.inner.clone(),
token: self.token, token: self.token,
addr: self.addr,
}) })
} }
fn create(&self) -> Box<Future<Item = Vec<(Token, BoxedServerService)>, Error = ()>> { fn create(&self) -> Box<Future<Item = Vec<(Token, BoxedServerService)>, Error = ()>> {
let token = self.token; let token = self.token;
let config = ServerConfig::new(self.addr);
Box::new( Box::new(
self.inner self.inner
.create() .create()
.new_service(&()) .new_service(&config)
.map_err(|_| ()) .map_err(|_| ())
.map(move |inner| { .map(move |inner| {
let service: BoxedServerService = Box::new(StreamService::new(inner)); let service: BoxedServerService = Box::new(StreamService::new(inner));
@ -155,7 +170,7 @@ impl InternalServiceFactory for Box<InternalServiceFactory> {
impl<F, T> ServiceFactory for F impl<F, T> ServiceFactory for F
where where
F: Fn() -> T + Send + Clone + 'static, F: Fn() -> T + Send + Clone + 'static,
T: NewService<TokioTcpStream>, T: NewService<ServerConfig, Request = TokioTcpStream>,
{ {
type NewService = T; type NewService = T;

View File

@ -1,6 +1,7 @@
use std::io; use std::io;
use std::marker::PhantomData; use std::marker::PhantomData;
use actix_server_config::ServerConfig;
use actix_service::{NewService, Service}; use actix_service::{NewService, Service};
use futures::{future::ok, future::FutureResult, Async, Future, Poll}; use futures::{future::ok, future::FutureResult, Async, Future, Poll};
use native_tls::{self, Error, HandshakeError, TlsAcceptor}; use native_tls::{self, Error, HandshakeError, TlsAcceptor};
@ -36,14 +37,17 @@ impl<T: AsyncRead + AsyncWrite> Clone for NativeTlsAcceptor<T> {
} }
} }
impl<T: AsyncRead + AsyncWrite> NewService<T> for NativeTlsAcceptor<T> { impl<T: AsyncRead + AsyncWrite> NewService<ServerConfig> for NativeTlsAcceptor<T> {
type Request = T;
type Response = TlsStream<T>; type Response = TlsStream<T>;
type Error = Error; type Error = Error;
type Service = NativeTlsAcceptorService<T>; type Service = NativeTlsAcceptorService<T>;
type InitError = (); type InitError = ();
type Future = FutureResult<Self::Service, Self::InitError>; type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self, _: &()) -> Self::Future { fn new_service(&self, cfg: &ServerConfig) -> Self::Future {
cfg.set_secure();
MAX_CONN_COUNTER.with(|conns| { MAX_CONN_COUNTER.with(|conns| {
ok(NativeTlsAcceptorService { ok(NativeTlsAcceptorService {
acceptor: self.acceptor.clone(), acceptor: self.acceptor.clone(),
@ -60,7 +64,8 @@ pub struct NativeTlsAcceptorService<T> {
conns: Counter, conns: Counter,
} }
impl<T: AsyncRead + AsyncWrite> Service<T> for NativeTlsAcceptorService<T> { impl<T: AsyncRead + AsyncWrite> Service for NativeTlsAcceptorService<T> {
type Request = T;
type Response = TlsStream<T>; type Response = TlsStream<T>;
type Error = Error; type Error = Error;
type Future = Accept<T>; type Future = Accept<T>;

View File

@ -8,6 +8,7 @@ use tokio_openssl::{AcceptAsync, SslAcceptorExt, SslStream};
use crate::counter::{Counter, CounterGuard}; use crate::counter::{Counter, CounterGuard};
use crate::ssl::MAX_CONN_COUNTER; use crate::ssl::MAX_CONN_COUNTER;
use crate::ServerConfig;
/// Support `SSL` connections via openssl package /// Support `SSL` connections via openssl package
/// ///
@ -36,14 +37,17 @@ impl<T: AsyncRead + AsyncWrite> Clone for OpensslAcceptor<T> {
} }
} }
impl<T: AsyncRead + AsyncWrite> NewService<T> for OpensslAcceptor<T> { impl<T: AsyncRead + AsyncWrite> NewService<ServerConfig> for OpensslAcceptor<T> {
type Request = T;
type Response = SslStream<T>; type Response = SslStream<T>;
type Error = HandshakeError<T>; type Error = HandshakeError<T>;
type Service = OpensslAcceptorService<T>; type Service = OpensslAcceptorService<T>;
type InitError = (); type InitError = ();
type Future = FutureResult<Self::Service, Self::InitError>; type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self, _: &()) -> Self::Future { fn new_service(&self, cfg: &ServerConfig) -> Self::Future {
cfg.set_secure();
MAX_CONN_COUNTER.with(|conns| { MAX_CONN_COUNTER.with(|conns| {
ok(OpensslAcceptorService { ok(OpensslAcceptorService {
acceptor: self.acceptor.clone(), acceptor: self.acceptor.clone(),
@ -60,7 +64,8 @@ pub struct OpensslAcceptorService<T> {
conns: Counter, conns: Counter,
} }
impl<T: AsyncRead + AsyncWrite> Service<T> for OpensslAcceptorService<T> { impl<T: AsyncRead + AsyncWrite> Service for OpensslAcceptorService<T> {
type Request = T;
type Response = SslStream<T>; type Response = SslStream<T>;
type Error = HandshakeError<T>; type Error = HandshakeError<T>;
type Future = OpensslAcceptorServiceFut<T>; type Future = OpensslAcceptorServiceFut<T>;

View File

@ -10,6 +10,7 @@ use tokio_rustls::{Accept, TlsAcceptor, TlsStream};
use crate::counter::{Counter, CounterGuard}; use crate::counter::{Counter, CounterGuard};
use crate::ssl::MAX_CONN_COUNTER; use crate::ssl::MAX_CONN_COUNTER;
use crate::ServerConfig as SrvConfig;
/// Support `SSL` connections via rustls package /// Support `SSL` connections via rustls package
/// ///
@ -38,14 +39,17 @@ impl<T> Clone for RustlsAcceptor<T> {
} }
} }
impl<T: AsyncRead + AsyncWrite> NewService<T> for RustlsAcceptor<T> { impl<T: AsyncRead + AsyncWrite> NewService<SrvConfig> for RustlsAcceptor<T> {
type Request = T;
type Response = TlsStream<T, ServerSession>; type Response = TlsStream<T, ServerSession>;
type Error = io::Error; type Error = io::Error;
type Service = RustlsAcceptorService<T>; type Service = RustlsAcceptorService<T>;
type InitError = (); type InitError = ();
type Future = FutureResult<Self::Service, Self::InitError>; type Future = FutureResult<Self::Service, Self::InitError>;
fn new_service(&self, _: &()) -> Self::Future { fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
cfg.set_secure();
MAX_CONN_COUNTER.with(|conns| { MAX_CONN_COUNTER.with(|conns| {
ok(RustlsAcceptorService { ok(RustlsAcceptorService {
acceptor: self.config.clone().into(), acceptor: self.config.clone().into(),
@ -62,7 +66,8 @@ pub struct RustlsAcceptorService<T> {
conns: Counter, conns: Counter,
} }
impl<T: AsyncRead + AsyncWrite> Service<T> for RustlsAcceptorService<T> { impl<T: AsyncRead + AsyncWrite> Service for RustlsAcceptorService<T> {
type Request = T;
type Response = TlsStream<T, ServerSession>; type Response = TlsStream<T, ServerSession>;
type Error = io::Error; type Error = io::Error;
type Future = RustlsAcceptorServiceFut<T>; type Future = RustlsAcceptorServiceFut<T>;

View File

@ -1,7 +1,7 @@
use std::{net, thread, time}; use std::{net, thread, time};
use actix_server::Server; use actix_server::{Server, ServerConfig};
use actix_service::fn_service; use actix_service::{fn_cfg_factory, fn_service, IntoService};
use net2::TcpBuilder; use net2::TcpBuilder;
fn unused_addr() -> net::SocketAddr { fn unused_addr() -> net::SocketAddr {
@ -19,7 +19,27 @@ fn test_bind() {
thread::spawn(move || { thread::spawn(move || {
Server::build() Server::build()
.bind("test", addr, || fn_service(|_| Ok::<_, ()>(()))) .bind("test", addr, move || {
fn_cfg_factory(move |cfg: &ServerConfig| {
assert_eq!(cfg.local_addr(), addr);
Ok::<_, ()>((|_| Ok::<_, ()>(())).into_service())
})
})
.unwrap()
.run()
});
thread::sleep(time::Duration::from_millis(500));
assert!(net::TcpStream::connect(addr).is_ok());
}
#[test]
fn test_bind_no_config() {
let addr = unused_addr();
thread::spawn(move || {
Server::build()
.bind("test", addr, move || fn_service(|_| Ok::<_, ()>(())))
.unwrap() .unwrap()
.run() .run()
}); });
@ -35,7 +55,12 @@ fn test_listen() {
thread::spawn(move || { thread::spawn(move || {
let lst = net::TcpListener::bind(addr).unwrap(); let lst = net::TcpListener::bind(addr).unwrap();
Server::build() Server::build()
.listen("test", lst, move || fn_service(|_| Ok::<_, ()>(()))) .listen("test", lst, move || {
fn_cfg_factory(move |cfg: &ServerConfig| {
assert_eq!(cfg.local_addr(), addr);
Ok::<_, ()>((|_| Ok::<_, ()>(())).into_service())
})
})
.unwrap() .unwrap()
.run() .run()
}); });