use std::{future::Future, io, net::SocketAddr, net::ToSocketAddrs};
use axum::Router;
use nidus_core::Application;
use tokio::net::TcpListener;
pub trait ApplicationHttpExt: Sized {
fn with_router(self, router: Router) -> HttpApplication;
}
impl ApplicationHttpExt for Application {
fn with_router(self, router: Router) -> HttpApplication {
HttpApplication {
application: self,
router,
}
}
}
pub struct HttpApplication {
application: Application,
router: Router,
}
impl HttpApplication {
pub const fn application(&self) -> &Application {
&self.application
}
pub const fn router(&self) -> &Router {
&self.router
}
pub fn map_router(self, map: impl FnOnce(Router) -> Router) -> Self {
Self {
application: self.application,
router: map(self.router),
}
}
pub fn into_router(self) -> Router {
self.router
}
pub async fn bind<A>(&self, address: A) -> io::Result<TcpListener>
where
A: ToSocketAddrs,
{
let address = address
.to_socket_addrs()?
.next()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "address resolved empty"))?;
TcpListener::bind(address).await
}
pub async fn listen<A>(self, address: A) -> io::Result<()>
where
A: ToSocketAddrs,
{
let listener = self.bind(address).await?;
axum::serve(
listener,
self.router
.into_make_service_with_connect_info::<SocketAddr>(),
)
.await
}
pub async fn listen_with_graceful_shutdown<A, F>(
self,
address: A,
shutdown: F,
) -> io::Result<()>
where
A: ToSocketAddrs,
F: Future<Output = ()> + Send + 'static,
{
let listener = self.bind(address).await?;
axum::serve(
listener,
self.router
.into_make_service_with_connect_info::<SocketAddr>(),
)
.with_graceful_shutdown(shutdown)
.await
}
pub async fn serve(self, listener: TcpListener) -> io::Result<()> {
axum::serve(
listener,
self.router
.into_make_service_with_connect_info::<SocketAddr>(),
)
.await
}
pub async fn serve_with_graceful_shutdown<F>(
self,
listener: TcpListener,
shutdown: F,
) -> io::Result<()>
where
F: Future<Output = ()> + Send + 'static,
{
axum::serve(
listener,
self.router
.into_make_service_with_connect_info::<SocketAddr>(),
)
.with_graceful_shutdown(shutdown)
.await
}
}