summaryrefslogtreecommitdiff
path: root/makima/src/server/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/server/mod.rs')
-rw-r--r--makima/src/server/mod.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/makima/src/server/mod.rs b/makima/src/server/mod.rs
new file mode 100644
index 0000000..c33eeef
--- /dev/null
+++ b/makima/src/server/mod.rs
@@ -0,0 +1,88 @@
+//! Web server module for the makima audio API.
+
+pub mod handlers;
+pub mod messages;
+pub mod openapi;
+pub mod state;
+
+use axum::{
+ routing::{get, post},
+ Router,
+};
+use tower_http::cors::{Any, CorsLayer};
+use tower_http::trace::TraceLayer;
+use utoipa::OpenApi;
+use utoipa_swagger_ui::SwaggerUi;
+
+use crate::server::handlers::{listen, tts};
+use crate::server::openapi::ApiDoc;
+use crate::server::state::SharedState;
+
+/// Create the axum Router with all routes configured.
+pub fn make_router(state: SharedState) -> Router {
+ // API v1 routes
+ let api_v1 = Router::new()
+ .route("/listen", get(listen::websocket_handler))
+ .route("/tts/synthesize", post(tts::synthesize_handler))
+ .with_state(state);
+
+ let swagger = SwaggerUi::new("/swagger-ui")
+ .url("/api-docs/openapi.json", ApiDoc::openapi());
+
+ Router::new()
+ .nest("/api/v1", api_v1)
+ .merge(swagger)
+ .layer(
+ CorsLayer::new()
+ .allow_origin(Any)
+ .allow_methods(Any)
+ .allow_headers(Any),
+ )
+ .layer(TraceLayer::new_for_http())
+}
+
+/// Run the HTTP server with graceful shutdown support.
+///
+/// # Arguments
+/// * `state` - Shared application state containing ML models
+/// * `addr` - Address to bind to (e.g., "0.0.0.0:8080")
+pub async fn run_server(state: SharedState, addr: &str) -> anyhow::Result<()> {
+ let app = make_router(state);
+ let listener = tokio::net::TcpListener::bind(addr).await?;
+
+ tracing::info!("Server listening on {}", addr);
+ tracing::info!("Swagger UI available at http://{}/swagger-ui", addr);
+
+ axum::serve(listener, app)
+ .with_graceful_shutdown(shutdown_signal())
+ .await?;
+
+ Ok(())
+}
+
+/// Wait for shutdown signals (Ctrl+C or SIGTERM).
+async fn shutdown_signal() {
+ let ctrl_c = async {
+ tokio::signal::ctrl_c()
+ .await
+ .expect("Failed to install Ctrl+C handler");
+ };
+
+ #[cfg(unix)]
+ let terminate = async {
+ tokio::signal::unix::signal(tokio::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 => {},
+ }
+
+ tracing::info!("Shutdown signal received, starting graceful shutdown");
+}