refactor: extract router/serve to server.rs, main is now thin orchestrator
This commit is contained in:
@@ -2,20 +2,14 @@
|
|||||||
//!
|
//!
|
||||||
//! Configures and starts the HTTP server with JWT-based authentication.
|
//! Configures and starts the HTTP server with JWT-based authentication.
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::Router;
|
|
||||||
use axum::http::{HeaderName, HeaderValue};
|
|
||||||
use tower_http::cors::{AllowHeaders, AllowMethods, AllowOrigin, CorsLayer};
|
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use domain::{ChannelService, IProviderRegistry, ScheduleEngineService, UserService};
|
use domain::{ChannelService, IProviderRegistry, ScheduleEngineService, UserService};
|
||||||
use infra::factory::{build_activity_log_repository, build_channel_repository, build_provider_config_repository, build_schedule_repository, build_user_repository};
|
use infra::factory::{build_activity_log_repository, build_channel_repository, build_provider_config_repository, build_schedule_repository, build_user_repository};
|
||||||
#[cfg(feature = "local-files")]
|
#[cfg(feature = "local-files")]
|
||||||
use infra::factory::build_transcode_settings_repository;
|
use infra::factory::build_transcode_settings_repository;
|
||||||
use k_core::http::server::{ServerConfig, apply_standard_middleware};
|
|
||||||
use tokio::net::TcpListener;
|
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod database;
|
mod database;
|
||||||
@@ -28,6 +22,7 @@ mod log_layer;
|
|||||||
mod poller;
|
mod poller;
|
||||||
mod routes;
|
mod routes;
|
||||||
mod scheduler;
|
mod scheduler;
|
||||||
|
mod server;
|
||||||
mod startup;
|
mod startup;
|
||||||
mod state;
|
mod state;
|
||||||
mod telemetry;
|
mod telemetry;
|
||||||
@@ -112,55 +107,11 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
*state.transcode_manager.write().await = Some(tm);
|
*state.transcode_manager.write().await = Some(tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
let server_config = ServerConfig {
|
|
||||||
cors_origins: config.cors_allowed_origins.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
startup::spawn_background_tasks(
|
startup::spawn_background_tasks(
|
||||||
Arc::clone(&state.schedule_engine),
|
Arc::clone(&state.schedule_engine),
|
||||||
bg_channel_repo,
|
bg_channel_repo,
|
||||||
event_tx,
|
event_tx,
|
||||||
);
|
);
|
||||||
|
|
||||||
let app = Router::new()
|
server::build_and_serve(state, &config).await
|
||||||
.nest("/api/v1", routes::api_v1_router())
|
|
||||||
.with_state(state);
|
|
||||||
|
|
||||||
let app = apply_standard_middleware(app, &server_config);
|
|
||||||
|
|
||||||
// Wrap with an outer CorsLayer that includes the custom password headers.
|
|
||||||
// Being outermost it handles OPTIONS preflights before k_core's inner layer.
|
|
||||||
let origins: Vec<HeaderValue> = config
|
|
||||||
.cors_allowed_origins
|
|
||||||
.iter()
|
|
||||||
.filter_map(|o| o.parse().ok())
|
|
||||||
.collect();
|
|
||||||
let cors = CorsLayer::new()
|
|
||||||
.allow_origin(AllowOrigin::list(origins))
|
|
||||||
.allow_methods(AllowMethods::any())
|
|
||||||
.allow_headers(AllowHeaders::list([
|
|
||||||
axum::http::header::AUTHORIZATION,
|
|
||||||
axum::http::header::CONTENT_TYPE,
|
|
||||||
HeaderName::from_static("x-channel-password"),
|
|
||||||
HeaderName::from_static("x-block-password"),
|
|
||||||
]));
|
|
||||||
let app = app.layer(cors);
|
|
||||||
|
|
||||||
let addr: SocketAddr = format!("{}:{}", config.host, config.port).parse()?;
|
|
||||||
let listener = TcpListener::bind(addr).await?;
|
|
||||||
|
|
||||||
tracing::info!("🚀 API server running at http://{}", addr);
|
|
||||||
tracing::info!("🔒 Authentication mode: JWT (Bearer token)");
|
|
||||||
|
|
||||||
#[cfg(feature = "auth-jwt")]
|
|
||||||
tracing::info!(" ✓ JWT auth enabled");
|
|
||||||
|
|
||||||
#[cfg(feature = "auth-oidc")]
|
|
||||||
tracing::info!(" ✓ OIDC integration enabled (stateless cookie state)");
|
|
||||||
|
|
||||||
tracing::info!("📝 API endpoints available at /api/v1/...");
|
|
||||||
|
|
||||||
axum::serve(listener, app).await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
59
k-tv-backend/api/src/server.rs
Normal file
59
k-tv-backend/api/src/server.rs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use axum::Router;
|
||||||
|
use axum::http::{HeaderName, HeaderValue};
|
||||||
|
use k_core::http::server::{ServerConfig, apply_standard_middleware};
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
use tower_http::cors::{AllowHeaders, AllowMethods, AllowOrigin, CorsLayer};
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::routes;
|
||||||
|
use crate::state::AppState;
|
||||||
|
|
||||||
|
pub async fn build_and_serve(state: AppState, config: &Config) -> anyhow::Result<()> {
|
||||||
|
let server_config = ServerConfig {
|
||||||
|
cors_origins: config.cors_allowed_origins.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.nest("/api/v1", routes::api_v1_router())
|
||||||
|
.with_state(state);
|
||||||
|
|
||||||
|
let app = apply_standard_middleware(app, &server_config);
|
||||||
|
|
||||||
|
// Wrap with an outer CorsLayer that includes the custom password headers.
|
||||||
|
// Being outermost it handles OPTIONS preflights before k_core's inner layer.
|
||||||
|
let origins: Vec<HeaderValue> = config
|
||||||
|
.cors_allowed_origins
|
||||||
|
.iter()
|
||||||
|
.filter_map(|o| o.parse().ok())
|
||||||
|
.collect();
|
||||||
|
let cors = CorsLayer::new()
|
||||||
|
.allow_origin(AllowOrigin::list(origins))
|
||||||
|
.allow_methods(AllowMethods::any())
|
||||||
|
.allow_headers(AllowHeaders::list([
|
||||||
|
axum::http::header::AUTHORIZATION,
|
||||||
|
axum::http::header::CONTENT_TYPE,
|
||||||
|
HeaderName::from_static("x-channel-password"),
|
||||||
|
HeaderName::from_static("x-block-password"),
|
||||||
|
]));
|
||||||
|
let app = app.layer(cors);
|
||||||
|
|
||||||
|
let addr: SocketAddr = format!("{}:{}", config.host, config.port).parse()?;
|
||||||
|
let listener = TcpListener::bind(addr).await?;
|
||||||
|
|
||||||
|
tracing::info!("🚀 API server running at http://{}", addr);
|
||||||
|
tracing::info!("🔒 Authentication mode: JWT (Bearer token)");
|
||||||
|
|
||||||
|
#[cfg(feature = "auth-jwt")]
|
||||||
|
tracing::info!(" ✓ JWT auth enabled");
|
||||||
|
|
||||||
|
#[cfg(feature = "auth-oidc")]
|
||||||
|
tracing::info!(" ✓ OIDC integration enabled (stateless cookie state)");
|
||||||
|
|
||||||
|
tracing::info!("📝 API endpoints available at /api/v1/...");
|
||||||
|
|
||||||
|
axum::serve(listener, app).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user