mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 08:22:59 +01:00
refactor acceptor service
This commit is contained in:
parent
6a61138bf8
commit
a3cfc24232
@ -1,9 +1,9 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::{io, mem, net, time};
|
use std::{io, mem, net, time};
|
||||||
|
|
||||||
use actix::{Actor, Addr, AsyncContext, Context, Handler, System};
|
use actix::{Actor, Addr, AsyncContext, Context, Handler, System};
|
||||||
use actix_net::{ssl, NewService, NewServiceExt, Server, Service};
|
use actix_net::server::{Server, ServerServiceFactory};
|
||||||
|
use actix_net::{ssl, NewService, NewServiceExt, Service};
|
||||||
|
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, FutureResult};
|
||||||
use futures::{Async, Poll, Stream};
|
use futures::{Async, Poll, Stream};
|
||||||
@ -36,11 +36,12 @@ struct Socket<H: IntoHttpHandler> {
|
|||||||
/// By default it serves HTTP2 when HTTPs is enabled,
|
/// By default it serves HTTP2 when HTTPs is enabled,
|
||||||
/// in order to change it, use `ServerFlags` that can be provided
|
/// in order to change it, use `ServerFlags` that can be provided
|
||||||
/// to acceptor service.
|
/// to acceptor service.
|
||||||
pub struct HttpServer<H>
|
pub struct HttpServer<H, F>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone,
|
||||||
{
|
{
|
||||||
factory: Arc<Fn() -> Vec<H> + Send + Sync>,
|
factory: F,
|
||||||
host: Option<String>,
|
host: Option<String>,
|
||||||
keep_alive: KeepAlive,
|
keep_alive: KeepAlive,
|
||||||
backlog: i32,
|
backlog: i32,
|
||||||
@ -54,21 +55,39 @@ where
|
|||||||
sockets: Vec<Socket<H>>,
|
sockets: Vec<Socket<H>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H> HttpServer<H>
|
impl<H, F> HttpServer<H, F>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
||||||
{
|
{
|
||||||
/// Create new http server with application factory
|
/// Create new http server with application factory
|
||||||
pub fn new<F, U>(factory: F) -> Self
|
pub fn new<F1, U>(factory: F1) -> HttpServer<H, impl Fn() -> Vec<H> + Send + Clone>
|
||||||
where
|
where
|
||||||
F: Fn() -> U + Sync + Send + 'static,
|
F1: Fn() -> U + Send + Clone,
|
||||||
U: IntoIterator<Item = H> + 'static,
|
U: IntoIterator<Item = H> + 'static,
|
||||||
{
|
{
|
||||||
let f = move || (factory)().into_iter().collect();
|
let f = move || (factory.clone())().into_iter().collect();
|
||||||
|
|
||||||
HttpServer {
|
HttpServer {
|
||||||
threads: num_cpus::get(),
|
threads: num_cpus::get(),
|
||||||
factory: Arc::new(f),
|
factory: f,
|
||||||
|
host: None,
|
||||||
|
backlog: 2048,
|
||||||
|
keep_alive: KeepAlive::Os,
|
||||||
|
shutdown_timeout: 30,
|
||||||
|
exit: false,
|
||||||
|
no_http2: false,
|
||||||
|
no_signals: false,
|
||||||
|
maxconn: 25_600,
|
||||||
|
maxconnrate: 256,
|
||||||
|
sockets: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn with_factory(factory: F) -> HttpServer<H, F> {
|
||||||
|
HttpServer {
|
||||||
|
factory,
|
||||||
|
threads: num_cpus::get(),
|
||||||
host: None,
|
host: None,
|
||||||
backlog: 2048,
|
backlog: 2048,
|
||||||
keep_alive: KeepAlive::Timeout(5),
|
keep_alive: KeepAlive::Timeout(5),
|
||||||
@ -211,6 +230,13 @@ where
|
|||||||
handler: Box::new(SimpleFactory {
|
handler: Box::new(SimpleFactory {
|
||||||
addr,
|
addr,
|
||||||
factory: self.factory.clone(),
|
factory: self.factory.clone(),
|
||||||
|
pipeline: DefaultPipelineFactory {
|
||||||
|
addr,
|
||||||
|
factory: self.factory.clone(),
|
||||||
|
host: self.host.clone(),
|
||||||
|
keep_alive: self.keep_alive,
|
||||||
|
_t: PhantomData,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -219,22 +245,30 @@ where
|
|||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Use listener for accepting incoming connection requests
|
/// Use listener for accepting incoming connection requests
|
||||||
pub(crate) fn listen_with<T, F>(mut self, lst: net::TcpListener, acceptor: F) -> Self
|
pub(crate) fn listen_with<T, A, Io>(
|
||||||
|
mut self, lst: net::TcpListener, acceptor: A,
|
||||||
|
) -> Self
|
||||||
where
|
where
|
||||||
F: Fn() -> T + Send + Clone + 'static,
|
A: AcceptorServiceFactory<Io = Io>,
|
||||||
T: NewService<Request = TcpStream, Error = (), InitError = ()> + Clone + 'static,
|
T: NewService<Request = TcpStream, Response = Io, Error = (), InitError = ()>
|
||||||
T::Response: IoStream,
|
+ Clone
|
||||||
|
+ 'static,
|
||||||
|
Io: IoStream + Send,
|
||||||
{
|
{
|
||||||
let addr = lst.local_addr().unwrap();
|
let addr = lst.local_addr().unwrap();
|
||||||
self.sockets.push(Socket {
|
self.sockets.push(Socket {
|
||||||
lst,
|
lst,
|
||||||
addr,
|
addr,
|
||||||
scheme: "https",
|
scheme: "https",
|
||||||
handler: Box::new(AcceptorFactory {
|
handler: Box::new(HttpServiceBuilder::new(
|
||||||
addr,
|
|
||||||
acceptor,
|
acceptor,
|
||||||
factory: self.factory.clone(),
|
DefaultPipelineFactory::new(
|
||||||
}),
|
self.factory.clone(),
|
||||||
|
self.host.clone(),
|
||||||
|
addr,
|
||||||
|
self.keep_alive,
|
||||||
|
),
|
||||||
|
)),
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -256,7 +290,7 @@ where
|
|||||||
///
|
///
|
||||||
/// This method sets alpn protocols to "h2" and "http/1.1"
|
/// This method sets alpn protocols to "h2" and "http/1.1"
|
||||||
pub fn listen_ssl(
|
pub fn listen_ssl(
|
||||||
self, lst: net::TcpListener, builder: SslAcceptorBuilder,
|
mut self, lst: net::TcpListener, builder: SslAcceptorBuilder,
|
||||||
) -> io::Result<Self> {
|
) -> io::Result<Self> {
|
||||||
use super::{openssl_acceptor_with_flags, ServerFlags};
|
use super::{openssl_acceptor_with_flags, ServerFlags};
|
||||||
|
|
||||||
@ -268,9 +302,23 @@ where
|
|||||||
|
|
||||||
let acceptor = openssl_acceptor_with_flags(builder, flags)?;
|
let acceptor = openssl_acceptor_with_flags(builder, flags)?;
|
||||||
|
|
||||||
Ok(self.listen_with(lst, move || {
|
let addr = lst.local_addr().unwrap();
|
||||||
ssl::OpensslAcceptor::new(acceptor.clone()).map_err(|_| ())
|
self.sockets.push(Socket {
|
||||||
}))
|
lst,
|
||||||
|
addr,
|
||||||
|
scheme: "https",
|
||||||
|
handler: Box::new(HttpServiceBuilder::new(
|
||||||
|
move || ssl::OpensslAcceptor::new(acceptor.clone()).map_err(|_| ()),
|
||||||
|
DefaultPipelineFactory::new(
|
||||||
|
self.factory.clone(),
|
||||||
|
self.host.clone(),
|
||||||
|
addr,
|
||||||
|
self.keep_alive,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[cfg(feature = "rust-tls")]
|
// #[cfg(feature = "rust-tls")]
|
||||||
@ -408,7 +456,7 @@ where
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: IntoHttpHandler> HttpServer<H> {
|
impl<H: IntoHttpHandler, F: Fn() -> Vec<H> + Send + Clone> HttpServer<H, F> {
|
||||||
/// Start listening for incoming connections.
|
/// Start listening for incoming connections.
|
||||||
///
|
///
|
||||||
/// This method starts number of http workers in separate threads.
|
/// This method starts number of http workers in separate threads.
|
||||||
@ -552,35 +600,35 @@ impl<H: IntoHttpHandler> HttpServer<H> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
struct HttpService<H, F, Io>
|
struct HttpService<F, H, Io>
|
||||||
where
|
where
|
||||||
H: HttpHandler,
|
F: Fn() -> Vec<H>,
|
||||||
F: IntoHttpHandler<Handler = H>,
|
H: IntoHttpHandler,
|
||||||
Io: IoStream,
|
Io: IoStream,
|
||||||
{
|
{
|
||||||
factory: Arc<Fn() -> Vec<F> + Send + Sync>,
|
factory: F,
|
||||||
addr: net::SocketAddr,
|
addr: net::SocketAddr,
|
||||||
host: Option<String>,
|
host: Option<String>,
|
||||||
keep_alive: KeepAlive,
|
keep_alive: KeepAlive,
|
||||||
_t: PhantomData<(H, Io)>,
|
_t: PhantomData<Io>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, F, Io> NewService for HttpService<H, F, Io>
|
impl<F, H, Io> NewService for HttpService<F, H, Io>
|
||||||
where
|
where
|
||||||
H: HttpHandler,
|
F: Fn() -> Vec<H>,
|
||||||
F: IntoHttpHandler<Handler = H>,
|
H: IntoHttpHandler,
|
||||||
Io: IoStream,
|
Io: IoStream,
|
||||||
{
|
{
|
||||||
type Request = Io;
|
type Request = Io;
|
||||||
type Response = ();
|
type Response = ();
|
||||||
type Error = ();
|
type Error = ();
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
type Service = HttpServiceHandler<H, Io>;
|
type Service = HttpServiceHandler<H::Handler, Io>;
|
||||||
type Future = FutureResult<Self::Service, Self::Error>;
|
type Future = FutureResult<Self::Service, Self::Error>;
|
||||||
|
|
||||||
fn new_service(&self) -> Self::Future {
|
fn new_service(&self) -> Self::Future {
|
||||||
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
||||||
let apps: Vec<_> = (*self.factory)()
|
let apps: Vec<_> = (self.factory)()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|h| h.into_handler())
|
.map(|h| h.into_handler())
|
||||||
.collect();
|
.collect();
|
||||||
@ -658,94 +706,43 @@ where
|
|||||||
) -> Server;
|
) -> Server;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimpleFactory<H>
|
struct SimpleFactory<H, F, P>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler,
|
H: IntoHttpHandler,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone,
|
||||||
|
P: HttpPipelineFactory<Io = TcpStream>,
|
||||||
{
|
{
|
||||||
pub addr: net::SocketAddr,
|
pub addr: net::SocketAddr,
|
||||||
pub factory: Arc<Fn() -> Vec<H> + Send + Sync>,
|
pub factory: F,
|
||||||
|
pub pipeline: P,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: IntoHttpHandler> Clone for SimpleFactory<H> {
|
impl<H: IntoHttpHandler, F, P> Clone for SimpleFactory<H, F, P>
|
||||||
|
where
|
||||||
|
P: HttpPipelineFactory<Io = TcpStream>,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone,
|
||||||
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
SimpleFactory {
|
SimpleFactory {
|
||||||
addr: self.addr,
|
addr: self.addr,
|
||||||
factory: self.factory.clone(),
|
factory: self.factory.clone(),
|
||||||
|
pipeline: self.pipeline.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H> ServiceFactory<H> for SimpleFactory<H>
|
impl<H, F, P> ServiceFactory<H> for SimpleFactory<H, F, P>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
||||||
|
P: HttpPipelineFactory<Io = TcpStream>,
|
||||||
{
|
{
|
||||||
fn register(
|
fn register(
|
||||||
&self, server: Server, lst: net::TcpListener, host: Option<String>,
|
&self, server: Server, lst: net::TcpListener, _host: Option<String>,
|
||||||
keep_alive: KeepAlive,
|
_keep_alive: KeepAlive,
|
||||||
) -> Server {
|
) -> Server {
|
||||||
let addr = self.addr;
|
let pipeline = self.pipeline.clone();
|
||||||
let factory = self.factory.clone();
|
server.listen(lst, move || pipeline.create())
|
||||||
|
|
||||||
server.listen(lst, move || HttpService {
|
|
||||||
keep_alive,
|
|
||||||
addr,
|
|
||||||
host: host.clone(),
|
|
||||||
factory: factory.clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AcceptorFactory<T, F, H>
|
|
||||||
where
|
|
||||||
F: Fn() -> T + Send + Clone + 'static,
|
|
||||||
T: NewService,
|
|
||||||
H: IntoHttpHandler,
|
|
||||||
{
|
|
||||||
pub addr: net::SocketAddr,
|
|
||||||
pub acceptor: F,
|
|
||||||
pub factory: Arc<Fn() -> Vec<H> + Send + Sync>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F, H> Clone for AcceptorFactory<T, F, H>
|
|
||||||
where
|
|
||||||
F: Fn() -> T + Send + Clone + 'static,
|
|
||||||
T: NewService,
|
|
||||||
H: IntoHttpHandler,
|
|
||||||
{
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
AcceptorFactory {
|
|
||||||
addr: self.addr,
|
|
||||||
acceptor: self.acceptor.clone(),
|
|
||||||
factory: self.factory.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F, H> ServiceFactory<H> for AcceptorFactory<T, F, H>
|
|
||||||
where
|
|
||||||
F: Fn() -> T + Send + Clone + 'static,
|
|
||||||
H: IntoHttpHandler + 'static,
|
|
||||||
T: NewService<Request = TcpStream, Error = (), InitError = ()> + Clone + 'static,
|
|
||||||
T::Response: IoStream,
|
|
||||||
{
|
|
||||||
fn register(
|
|
||||||
&self, server: Server, lst: net::TcpListener, host: Option<String>,
|
|
||||||
keep_alive: KeepAlive,
|
|
||||||
) -> Server {
|
|
||||||
let addr = self.addr;
|
|
||||||
let factory = self.factory.clone();
|
|
||||||
let acceptor = self.acceptor.clone();
|
|
||||||
|
|
||||||
server.listen(lst, move || {
|
|
||||||
(acceptor)().and_then(HttpService {
|
|
||||||
keep_alive,
|
|
||||||
addr,
|
|
||||||
host: host.clone(),
|
|
||||||
factory: factory.clone(),
|
|
||||||
_t: PhantomData,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,3 +757,186 @@ fn create_tcp_listener(
|
|||||||
builder.bind(addr)?;
|
builder.bind(addr)?;
|
||||||
Ok(builder.listen(backlog)?)
|
Ok(builder.listen(backlog)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct HttpServiceBuilder<H, A, P> {
|
||||||
|
acceptor: A,
|
||||||
|
pipeline: P,
|
||||||
|
t: PhantomData<H>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, A, P> HttpServiceBuilder<H, A, P>
|
||||||
|
where
|
||||||
|
A: AcceptorServiceFactory,
|
||||||
|
P: HttpPipelineFactory<Io = A::Io>,
|
||||||
|
H: IntoHttpHandler,
|
||||||
|
{
|
||||||
|
pub fn new(acceptor: A, pipeline: P) -> Self {
|
||||||
|
Self {
|
||||||
|
acceptor,
|
||||||
|
pipeline,
|
||||||
|
t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn acceptor<A1>(self, acceptor: A1) -> HttpServiceBuilder<H, A1, P>
|
||||||
|
where
|
||||||
|
A1: AcceptorServiceFactory,
|
||||||
|
{
|
||||||
|
HttpServiceBuilder {
|
||||||
|
acceptor,
|
||||||
|
pipeline: self.pipeline,
|
||||||
|
t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pipeline<P1>(self, pipeline: P1) -> HttpServiceBuilder<H, A, P1>
|
||||||
|
where
|
||||||
|
P1: HttpPipelineFactory,
|
||||||
|
{
|
||||||
|
HttpServiceBuilder {
|
||||||
|
pipeline,
|
||||||
|
acceptor: self.acceptor,
|
||||||
|
t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&self) -> impl ServerServiceFactory {
|
||||||
|
let acceptor = self.acceptor.clone();
|
||||||
|
let pipeline = self.pipeline.clone();
|
||||||
|
|
||||||
|
move || acceptor.create().and_then(pipeline.create())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, A, P> ServiceFactory<H> for HttpServiceBuilder<H, A, P>
|
||||||
|
where
|
||||||
|
A: AcceptorServiceFactory,
|
||||||
|
P: HttpPipelineFactory<Io = A::Io>,
|
||||||
|
H: IntoHttpHandler,
|
||||||
|
{
|
||||||
|
fn register(
|
||||||
|
&self, server: Server, lst: net::TcpListener, _host: Option<String>,
|
||||||
|
_keep_alive: KeepAlive,
|
||||||
|
) -> Server {
|
||||||
|
server.listen(lst, self.finish())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AcceptorServiceFactory: Send + Clone + 'static {
|
||||||
|
type Io: IoStream + Send;
|
||||||
|
type NewService: NewService<
|
||||||
|
Request = TcpStream,
|
||||||
|
Response = Self::Io,
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>;
|
||||||
|
|
||||||
|
fn create(&self) -> Self::NewService;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, T> AcceptorServiceFactory for F
|
||||||
|
where
|
||||||
|
F: Fn() -> T + Send + Clone + 'static,
|
||||||
|
T::Response: IoStream + Send,
|
||||||
|
T: NewService<Request = TcpStream, Error = (), InitError = ()>,
|
||||||
|
{
|
||||||
|
type Io = T::Response;
|
||||||
|
type NewService = T;
|
||||||
|
|
||||||
|
fn create(&self) -> T {
|
||||||
|
(self)()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait HttpPipelineFactory: Send + Clone + 'static {
|
||||||
|
type Io: IoStream;
|
||||||
|
type NewService: NewService<
|
||||||
|
Request = Self::Io,
|
||||||
|
Response = (),
|
||||||
|
Error = (),
|
||||||
|
InitError = (),
|
||||||
|
>;
|
||||||
|
|
||||||
|
fn create(&self) -> Self::NewService;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, T> HttpPipelineFactory for F
|
||||||
|
where
|
||||||
|
F: Fn() -> T + Send + Clone + 'static,
|
||||||
|
T: NewService<Response = (), Error = (), InitError = ()>,
|
||||||
|
T::Request: IoStream,
|
||||||
|
{
|
||||||
|
type Io = T::Request;
|
||||||
|
type NewService = T;
|
||||||
|
|
||||||
|
fn create(&self) -> T {
|
||||||
|
(self)()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DefaultPipelineFactory<F, H, Io>
|
||||||
|
where
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone,
|
||||||
|
{
|
||||||
|
factory: F,
|
||||||
|
host: Option<String>,
|
||||||
|
addr: net::SocketAddr,
|
||||||
|
keep_alive: KeepAlive,
|
||||||
|
_t: PhantomData<Io>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, H, Io> DefaultPipelineFactory<F, H, Io>
|
||||||
|
where
|
||||||
|
Io: IoStream + Send,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
||||||
|
H: IntoHttpHandler + 'static,
|
||||||
|
{
|
||||||
|
fn new(
|
||||||
|
factory: F, host: Option<String>, addr: net::SocketAddr, keep_alive: KeepAlive,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
factory,
|
||||||
|
addr,
|
||||||
|
keep_alive,
|
||||||
|
host,
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, H, Io> Clone for DefaultPipelineFactory<F, H, Io>
|
||||||
|
where
|
||||||
|
Io: IoStream,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone,
|
||||||
|
H: IntoHttpHandler,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
factory: self.factory.clone(),
|
||||||
|
addr: self.addr,
|
||||||
|
keep_alive: self.keep_alive,
|
||||||
|
host: self.host.clone(),
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, H, Io> HttpPipelineFactory for DefaultPipelineFactory<F, H, Io>
|
||||||
|
where
|
||||||
|
Io: IoStream + Send,
|
||||||
|
F: Fn() -> Vec<H> + Send + Clone + 'static,
|
||||||
|
H: IntoHttpHandler + 'static,
|
||||||
|
{
|
||||||
|
type Io = Io;
|
||||||
|
type NewService = HttpService<F, H, Io>;
|
||||||
|
|
||||||
|
fn create(&self) -> Self::NewService {
|
||||||
|
HttpService {
|
||||||
|
addr: self.addr,
|
||||||
|
keep_alive: self.keep_alive,
|
||||||
|
host: self.host.clone(),
|
||||||
|
factory: self.factory.clone(),
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -174,13 +174,13 @@ const HW_BUFFER_SIZE: usize = 32_768;
|
|||||||
/// sys.run();
|
/// sys.run();
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new<F, U, H>(factory: F) -> HttpServer<H>
|
pub fn new<F, U, H>(factory: F) -> HttpServer<H, impl Fn() -> Vec<H> + Send + Clone>
|
||||||
where
|
where
|
||||||
F: Fn() -> U + Sync + Send + 'static,
|
F: Fn() -> U + Send + Clone + 'static,
|
||||||
U: IntoIterator<Item = H> + 'static,
|
U: IntoIterator<Item = H>,
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
{
|
{
|
||||||
HttpServer::new(factory)
|
HttpServer::with_factory(move || (factory.clone())().into_iter().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
38
src/test.rs
38
src/test.rs
@ -79,13 +79,13 @@ impl TestServer {
|
|||||||
/// middlewares or set handlers for test application.
|
/// middlewares or set handlers for test application.
|
||||||
pub fn new<F>(config: F) -> Self
|
pub fn new<F>(config: F) -> Self
|
||||||
where
|
where
|
||||||
F: Sync + Send + 'static + Fn(&mut TestApp<()>),
|
F: Clone + Send + 'static + Fn(&mut TestApp<()>),
|
||||||
{
|
{
|
||||||
TestServerBuilder::new(|| ()).start(config)
|
TestServerBuilder::new(|| ()).start(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create test server builder
|
/// Create test server builder
|
||||||
pub fn build() -> TestServerBuilder<()> {
|
pub fn build() -> TestServerBuilder<(), impl Fn() -> () + Clone + Send + 'static> {
|
||||||
TestServerBuilder::new(|| ())
|
TestServerBuilder::new(|| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +94,9 @@ impl TestServer {
|
|||||||
/// This method can be used for constructing application state.
|
/// This method can be used for constructing application state.
|
||||||
/// Also it can be used for external dependency initialization,
|
/// Also it can be used for external dependency initialization,
|
||||||
/// like creating sync actors for diesel integration.
|
/// like creating sync actors for diesel integration.
|
||||||
pub fn build_with_state<F, S>(state: F) -> TestServerBuilder<S>
|
pub fn build_with_state<S, F>(state: F) -> TestServerBuilder<S, F>
|
||||||
where
|
where
|
||||||
F: Fn() -> S + Sync + Send + 'static,
|
F: Fn() -> S + Clone + Send + 'static,
|
||||||
S: 'static,
|
S: 'static,
|
||||||
{
|
{
|
||||||
TestServerBuilder::new(state)
|
TestServerBuilder::new(state)
|
||||||
@ -105,11 +105,12 @@ impl TestServer {
|
|||||||
/// Start new test server with application factory
|
/// Start new test server with application factory
|
||||||
pub fn with_factory<F, U, H>(factory: F) -> Self
|
pub fn with_factory<F, U, H>(factory: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn() -> U + Sync + Send + 'static,
|
F: Fn() -> U + Send + Clone + 'static,
|
||||||
U: IntoIterator<Item = H> + 'static,
|
U: IntoIterator<Item = H>,
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
{
|
{
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
let factory = move || (factory.clone())().into_iter().collect();
|
||||||
|
|
||||||
// run server in separate thread
|
// run server in separate thread
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
@ -117,7 +118,7 @@ impl TestServer {
|
|||||||
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
let local_addr = tcp.local_addr().unwrap();
|
let local_addr = tcp.local_addr().unwrap();
|
||||||
|
|
||||||
HttpServer::new(factory)
|
let _ = HttpServer::with_factory(factory)
|
||||||
.disable_signals()
|
.disable_signals()
|
||||||
.listen(tcp)
|
.listen(tcp)
|
||||||
.keep_alive(5)
|
.keep_alive(5)
|
||||||
@ -261,22 +262,25 @@ impl Drop for TestServer {
|
|||||||
///
|
///
|
||||||
/// This type can be used to construct an instance of `TestServer` through a
|
/// This type can be used to construct an instance of `TestServer` through a
|
||||||
/// builder-like pattern.
|
/// builder-like pattern.
|
||||||
pub struct TestServerBuilder<S> {
|
pub struct TestServerBuilder<S, F>
|
||||||
state: Box<Fn() -> S + Sync + Send + 'static>,
|
where
|
||||||
|
F: Fn() -> S + Send + Clone + 'static,
|
||||||
|
{
|
||||||
|
state: F,
|
||||||
#[cfg(feature = "alpn")]
|
#[cfg(feature = "alpn")]
|
||||||
ssl: Option<SslAcceptorBuilder>,
|
ssl: Option<SslAcceptorBuilder>,
|
||||||
#[cfg(feature = "rust-tls")]
|
#[cfg(feature = "rust-tls")]
|
||||||
rust_ssl: Option<ServerConfig>,
|
rust_ssl: Option<ServerConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: 'static> TestServerBuilder<S> {
|
impl<S: 'static, F> TestServerBuilder<S, F>
|
||||||
/// Create a new test server
|
|
||||||
pub fn new<F>(state: F) -> TestServerBuilder<S>
|
|
||||||
where
|
where
|
||||||
F: Fn() -> S + Sync + Send + 'static,
|
F: Fn() -> S + Send + Clone + 'static,
|
||||||
{
|
{
|
||||||
|
/// Create a new test server
|
||||||
|
pub fn new(state: F) -> TestServerBuilder<S, F> {
|
||||||
TestServerBuilder {
|
TestServerBuilder {
|
||||||
state: Box::new(state),
|
state,
|
||||||
#[cfg(feature = "alpn")]
|
#[cfg(feature = "alpn")]
|
||||||
ssl: None,
|
ssl: None,
|
||||||
#[cfg(feature = "rust-tls")]
|
#[cfg(feature = "rust-tls")]
|
||||||
@ -300,9 +304,9 @@ impl<S: 'static> TestServerBuilder<S> {
|
|||||||
|
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
/// Configure test application and run test server
|
/// Configure test application and run test server
|
||||||
pub fn start<F>(mut self, config: F) -> TestServer
|
pub fn start<C>(mut self, config: C) -> TestServer
|
||||||
where
|
where
|
||||||
F: Sync + Send + 'static + Fn(&mut TestApp<S>),
|
C: Fn(&mut TestApp<S>) + Clone + Send + 'static,
|
||||||
{
|
{
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
@ -324,7 +328,7 @@ impl<S: 'static> TestServerBuilder<S> {
|
|||||||
|
|
||||||
let sys = System::new("actix-test-server");
|
let sys = System::new("actix-test-server");
|
||||||
let state = self.state;
|
let state = self.state;
|
||||||
let mut srv = HttpServer::new(move || {
|
let mut srv = HttpServer::with_factory(move || {
|
||||||
let mut app = TestApp::new(state());
|
let mut app = TestApp::new(state());
|
||||||
config(&mut app);
|
config(&mut app);
|
||||||
vec![app]
|
vec![app]
|
||||||
|
Loading…
Reference in New Issue
Block a user