90 lines
2.3 KiB
Rust
90 lines
2.3 KiB
Rust
use std::{net::SocketAddr, sync::Arc};
|
|
|
|
use axum::Router;
|
|
use futures::try_join;
|
|
use tokio::signal;
|
|
|
|
use super::{builder::AppBuilder, context::AppContextTrait};
|
|
use crate::{
|
|
errors::RResult,
|
|
web::{
|
|
controller::{self, core::ControllerTrait},
|
|
middleware::default_middleware_stack,
|
|
},
|
|
};
|
|
|
|
pub struct App {
|
|
pub context: Arc<dyn AppContextTrait>,
|
|
pub builder: AppBuilder,
|
|
}
|
|
|
|
impl App {
|
|
pub fn builder() -> AppBuilder {
|
|
AppBuilder::default()
|
|
}
|
|
|
|
pub async fn serve(&self) -> RResult<()> {
|
|
let context = &self.context;
|
|
let config = context.config();
|
|
let listener = tokio::net::TcpListener::bind(&format!(
|
|
"{}:{}",
|
|
config.server.binding, config.server.port
|
|
))
|
|
.await?;
|
|
|
|
let mut router = Router::<Arc<dyn AppContextTrait>>::new();
|
|
|
|
let (graphqlc, oidcc) = try_join!(
|
|
controller::graphql::create(context.clone()),
|
|
controller::oidc::create(context.clone()),
|
|
)?;
|
|
|
|
for c in [graphqlc, oidcc] {
|
|
router = c.apply_to(router);
|
|
}
|
|
|
|
let middlewares = default_middleware_stack(context.clone());
|
|
for mid in middlewares {
|
|
router = mid.apply(router)?;
|
|
tracing::info!(name = mid.name(), "+middleware");
|
|
}
|
|
|
|
let router = router
|
|
.with_state(context.clone())
|
|
.into_make_service_with_connect_info::<SocketAddr>();
|
|
|
|
axum::serve(listener, router)
|
|
.with_graceful_shutdown(async move {
|
|
Self::shutdown_signal().await;
|
|
tracing::info!("shutting down...");
|
|
})
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn shutdown_signal() {
|
|
let ctrl_c = async {
|
|
signal::ctrl_c()
|
|
.await
|
|
.expect("failed to install Ctrl+C handler");
|
|
};
|
|
|
|
#[cfg(unix)]
|
|
let terminate = async {
|
|
signal::unix::signal(signal::unix::SignalKind::terminate())
|
|
.expect("failed to install signal handler")
|
|
.recv()
|
|
.await;
|
|
};
|
|
|
|
#[cfg(not(unix))]
|
|
let terminate = std::future::pending::<()>();
|
|
|
|
tokio::select! {
|
|
() = ctrl_c => {},
|
|
() = terminate => {},
|
|
}
|
|
}
|
|
}
|