#[cfg(unix)]
use std::path::PathBuf;
use tako_rs_core::router::Router;
use super::handle::ServerHandle;
use super::spawn::make_handle;
use super::spawn::spawn_done_compio;
#[cfg(feature = "compio-tls")]
use super::spawn::tls_alpn_for_tcp;
#[cfg(any(feature = "compio-tls", feature = "http3"))]
use super::tls_cert::TlsCert;
#[cfg(any(feature = "compio-tls", feature = "http3"))]
use super::tls_cert::build_rustls_server_config;
use crate::ServerConfig;
#[derive(Debug, Default, Clone)]
pub struct CompioServerBuilder {
config: ServerConfig,
#[cfg(any(feature = "compio-tls", feature = "http3"))]
tls: Option<TlsCert>,
}
impl CompioServerBuilder {
#[must_use]
pub fn config(mut self, config: ServerConfig) -> Self {
self.config = config;
self
}
#[cfg(any(feature = "compio-tls", feature = "http3"))]
#[must_use]
pub fn tls(mut self, cert: TlsCert) -> Self {
self.tls = Some(cert);
self
}
pub fn build(self) -> CompioServer {
CompioServer {
config: self.config,
#[cfg(any(feature = "compio-tls", feature = "http3"))]
tls: self.tls,
}
}
}
#[derive(Debug, Clone)]
pub struct CompioServer {
config: ServerConfig,
#[cfg(any(feature = "compio-tls", feature = "http3"))]
tls: Option<TlsCert>,
}
impl CompioServer {
#[must_use]
pub fn builder() -> CompioServerBuilder {
CompioServerBuilder::default()
}
#[inline]
pub fn config(&self) -> &ServerConfig {
&self.config
}
pub fn spawn_http(&self, listener: compio::net::TcpListener, router: Router) -> ServerHandle {
self
.try_spawn_http(listener, router)
.unwrap_or_else(|error| super::spawn::failed_handle(error, self.config.drain_timeout))
}
pub fn try_spawn_http(
&self,
listener: compio::net::TcpListener,
router: Router,
) -> Result<ServerHandle, tako_rs_core::types::BoxError> {
#[cfg(feature = "plugins")]
router.setup_plugins_once()?;
let (handle, signal) = make_handle(self.config.drain_timeout, Some(listener.local_addr()?));
spawn_done_compio(
&handle,
crate::server_compio::run(listener, router, signal, self.config.clone()),
);
Ok(handle)
}
#[cfg(feature = "http2")]
pub fn spawn_h2c(&self, listener: compio::net::TcpListener, router: Router) -> ServerHandle {
self
.try_spawn_h2c(listener, router)
.unwrap_or_else(|error| super::spawn::failed_handle(error, self.config.drain_timeout))
}
#[cfg(feature = "http2")]
pub fn try_spawn_h2c(
&self,
listener: compio::net::TcpListener,
router: Router,
) -> Result<ServerHandle, tako_rs_core::types::BoxError> {
#[cfg(feature = "plugins")]
router.setup_plugins_once()?;
let (handle, signal) = make_handle(self.config.drain_timeout, Some(listener.local_addr()?));
spawn_done_compio(
&handle,
crate::server_compio::run_h2c(listener, router, signal, self.config.clone()),
);
Ok(handle)
}
#[cfg(feature = "proxy-protocol")]
pub fn spawn_proxy_protocol(
&self,
listener: compio::net::TcpListener,
router: Router,
) -> ServerHandle {
self
.try_spawn_proxy_protocol(listener, router)
.unwrap_or_else(|error| super::spawn::failed_handle(error, self.config.drain_timeout))
}
#[cfg(feature = "proxy-protocol")]
pub fn try_spawn_proxy_protocol(
&self,
listener: compio::net::TcpListener,
router: Router,
) -> Result<ServerHandle, tako_rs_core::types::BoxError> {
#[cfg(feature = "plugins")]
router.setup_plugins_once()?;
let (handle, signal) = make_handle(self.config.drain_timeout, Some(listener.local_addr()?));
spawn_done_compio(
&handle,
crate::server_compio::run_proxy_protocol(listener, router, signal, self.config.clone()),
);
Ok(handle)
}
#[cfg(unix)]
pub fn spawn_unix_http(&self, path: impl Into<PathBuf>, router: Router) -> ServerHandle {
let path = path.into();
let config = self.config.clone();
let (handle, signal) = make_handle(config.drain_timeout, None);
spawn_done_compio(&handle, async move {
let listener = crate::server_compio::unix::UnixSocketListener::bind(path).await?;
crate::server_compio::run_unix(listener, router, signal, config).await
});
handle
}
#[cfg(unix)]
pub async fn try_spawn_unix_http(
&self,
path: impl Into<PathBuf>,
router: Router,
) -> Result<ServerHandle, tako_rs_core::types::BoxError> {
#[cfg(feature = "plugins")]
router.setup_plugins_once()?;
let listener = crate::server_compio::unix::UnixSocketListener::bind(path.into()).await?;
let config = self.config.clone();
let (handle, signal) = make_handle(config.drain_timeout, None);
spawn_done_compio(
&handle,
crate::server_compio::run_unix(listener, router, signal, config),
);
Ok(handle)
}
#[cfg(feature = "compio-tls")]
pub fn spawn_tls(&self, listener: compio::net::TcpListener, router: Router) -> ServerHandle {
self
.try_spawn_tls(listener, router)
.unwrap_or_else(|error| super::spawn::failed_handle(error, self.config.drain_timeout))
}
#[cfg(feature = "compio-tls")]
pub fn try_spawn_tls(
&self,
listener: compio::net::TcpListener,
router: Router,
) -> Result<ServerHandle, tako_rs_core::types::BoxError> {
let tls = self
.tls
.as_ref()
.ok_or("TLS certificate configuration is required")?;
let tls = build_rustls_server_config(tls, tls_alpn_for_tcp())?;
#[cfg(feature = "plugins")]
router.setup_plugins_once()?;
let (handle, signal) = make_handle(self.config.drain_timeout, Some(listener.local_addr()?));
spawn_done_compio(
&handle,
crate::server_tls_compio::run_with_config(
listener,
router,
tls,
Some(signal),
self.config.clone(),
),
);
Ok(handle)
}
#[cfg(feature = "http3")]
pub fn spawn_h3(&self, addr: impl Into<String>, router: Router) -> ServerHandle {
self
.try_spawn_h3(addr, router)
.unwrap_or_else(|error| super::spawn::failed_handle(error, self.config.drain_timeout))
}
#[cfg(feature = "http3")]
pub fn try_spawn_h3(
&self,
addr: impl Into<String>,
router: Router,
) -> Result<ServerHandle, tako_rs_core::types::BoxError> {
let tls = self
.tls
.as_ref()
.ok_or("TLS certificate configuration is required")?;
let tls = build_rustls_server_config(tls, vec![b"h3".to_vec()])?;
#[cfg(feature = "plugins")]
router.setup_plugins_once()?;
let endpoint = crate::server_compio::h3::bind_endpoint(&addr.into(), &tls, &self.config)?;
let (handle, signal) = make_handle(self.config.drain_timeout, Some(endpoint.local_addr()?));
spawn_done_compio(
&handle,
crate::server_compio::h3::run_endpoint(endpoint, router, signal, self.config.clone()),
);
Ok(handle)
}
}