use std::process::ExitCode;
use std::sync::Arc;
use std::time::Duration;
use tokio::net::ToSocketAddrs;
use crate::app::{AppService, Via};
use crate::error::Error;
#[cfg(any(feature = "native-tls", feature = "rustls"))]
use super::tls;
pub struct Server<App> {
app: Via<App>,
config: ServerConfig,
}
#[derive(Debug)]
pub(super) struct ServerConfig {
pub(super) max_connections: usize,
pub(super) max_request_size: usize,
pub(super) shutdown_timeout: Duration,
}
impl<App> Server<App>
where
App: Send + Sync + 'static,
{
pub fn new(app: Via<App>) -> Self {
Self {
app,
config: Default::default(),
}
}
pub fn max_connections(self, max_connections: usize) -> Self {
Self {
config: ServerConfig {
max_connections,
..self.config
},
..self
}
}
pub fn max_request_size(self, max_request_size: usize) -> Self {
Self {
config: ServerConfig {
max_request_size,
..self.config
},
..self
}
}
pub fn shutdown_timeout(self, shutdown_timeout: Duration) -> Self {
Self {
config: ServerConfig {
shutdown_timeout,
..self.config
},
..self
}
}
pub fn listen<A>(self, address: A) -> impl Future<Output = Result<ExitCode, Error>>
where
A: ToSocketAddrs,
{
use tokio::net::TcpListener;
let Self { app, config } = self;
let service = AppService::new(Arc::new(app), config.max_request_size);
async {
let exit = super::accept(
config,
TcpListener::bind(address).await?,
Box::new(|stream| async { Ok(stream) }),
service,
);
Ok(exit.await)
}
}
#[cfg(feature = "native-tls")]
pub fn listen_native_tls<A>(
self,
address: A,
tls_config: native_tls::Identity,
) -> impl Future<Output = Result<ExitCode, Error>>
where
A: ToSocketAddrs,
{
let Self { app, config, .. } = self;
let service = AppService::new(Arc::new(app), config.max_request_size);
tls::listen_native_tls(config, address, tls_config, service)
}
#[cfg(feature = "rustls")]
pub fn listen_rustls<A>(
self,
address: A,
tls_config: rustls::ServerConfig,
) -> impl Future<Output = Result<ExitCode, Error>>
where
A: ToSocketAddrs,
{
let Self { app, config, .. } = self;
let service = AppService::new(Arc::new(app), config.max_request_size);
tls::listen_rustls(config, address, tls_config, service)
}
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
max_connections: 1000,
max_request_size: 104_857_600, shutdown_timeout: Duration::from_secs(30),
}
}
}