use crate::builder::ServerBuilder;
use crate::error::{Error, Result};
use crate::shutdown::shutdown_signal;
use axum::Router;
use std::net::SocketAddr;
use std::time::Duration;
use tokio::net::TcpListener;
pub struct Server {
router: Router<()>,
listener: TcpListener,
local_addr: SocketAddr,
shutdown_timeout: Option<Duration>,
}
impl Server {
pub fn builder() -> ServerBuilder {
ServerBuilder::new()
}
pub(crate) fn from_parts(
router: Router<()>,
listener: TcpListener,
local_addr: SocketAddr,
shutdown_timeout: Option<Duration>,
) -> Self {
Self {
router,
listener,
local_addr,
shutdown_timeout,
}
}
#[must_use]
pub fn local_addr(&self) -> SocketAddr {
self.local_addr
}
pub async fn run(self) -> Result<()> {
self.run_with_shutdown(shutdown_signal()).await
}
pub async fn run_with_shutdown<F>(self, shutdown: F) -> Result<()>
where
F: std::future::Future<Output = ()> + Send + 'static,
{
let timeout = self.shutdown_timeout;
let serve = axum::serve(self.listener, self.router).with_graceful_shutdown(shutdown);
match timeout {
Some(d) => match tokio::time::timeout(d, serve).await {
Ok(res) => res.map_err(Error::from),
Err(_) => Err(Error::ShutdownTimeout(d)),
},
None => serve.await.map_err(Error::from),
}
}
}