omni_director/api_clean/
server.rs1use super::handlers::*;
6use super::middleware::*;
7use crate::routing::Router;
8use crate::providers::{ProviderRegistry, EventRegistry};
9use axum::{
10 middleware,
11 routing::{get, post},
12 Router as AxumRouter,
13};
14use std::sync::Arc;
15use std::time::SystemTime;
16use tower_http::cors::CorsLayer;
17use tower_http::trace::TraceLayer;
18
19#[derive(Debug, Clone)]
21pub struct ServerConfig {
22 pub bind_address: String,
24 pub enable_cors: bool,
26 pub enable_logging: bool,
28 pub request_timeout_seconds: u64,
30}
31
32impl Default for ServerConfig {
33 fn default() -> Self {
34 Self {
35 bind_address: "127.0.0.1:8080".to_string(),
36 enable_cors: true,
37 enable_logging: true,
38 request_timeout_seconds: 30,
39 }
40 }
41}
42
43pub fn create_server(
45 registry: Arc<ProviderRegistry>,
46 router: Arc<Router>,
47 event_registry: Arc<EventRegistry>,
48 config: ServerConfig,
49) -> AxumRouter {
50 let state = AppState {
51 router,
52 registry,
53 event_registry,
54 start_time: SystemTime::now(),
55 };
56
57 let mut app = AxumRouter::new()
58 .route("/health", get(health))
60 .route("/stats", get(get_stats))
61 .route("/routes", get(list_routes))
62
63 .route("/providers", get(discover_providers))
65 .route("/providers/:provider", get(get_provider))
66
67 .route("/providers/:provider/features/:feature", get(get_feature))
69
70 .route(
72 "/providers/:provider/features/:feature/operations/:operation",
73 get(get_operation).post(execute_operation),
74 )
75
76 .route("/exec_action", post(exec_action))
78
79 .with_state(state);
81
82 if config.enable_logging {
84 app = app.layer(TraceLayer::new_for_http());
85 }
86
87 if config.enable_cors {
88 app = app.layer(CorsLayer::permissive());
89 }
90
91 app = app.layer(middleware::from_fn(request_logging_middleware));
93 app = app.layer(middleware::from_fn(error_handling_middleware));
94
95 app
96}
97
98pub async fn start_server(
100 registry: Arc<ProviderRegistry>,
101 router: Arc<Router>,
102 event_registry: Arc<EventRegistry>,
103 config: ServerConfig,
104) -> Result<(), Box<dyn std::error::Error>> {
105 let app = create_server(registry, router, event_registry, config.clone());
106
107 println!("🚀 Starting OmniDirector API server on {}", config.bind_address);
108 println!("📚 API Documentation:");
109 print_api_routes();
110
111 let listener = tokio::net::TcpListener::bind(&config.bind_address).await?;
112
113 axum::serve(listener, app).await?;
114
115 Ok(())
116}
117
118fn print_api_routes() {
120 println!(" GET /health - Health check");
121 println!(" GET /stats - Registry statistics");
122 println!(" GET /routes - List all available routes");
123 println!(" GET /providers - Discover all providers");
124 println!(" GET /providers/{{provider}} - Get provider information");
125 println!(" GET /providers/{{provider}}/features/{{feature}} - Get feature information");
126 println!(" GET /providers/{{provider}}/features/{{feature}}/operations/{{operation}} - Get operation information");
127 println!(" POST /providers/{{provider}}/features/{{feature}}/operations/{{operation}} - Execute operation");
128 println!();
129 println!("🔗 Example URLs:");
130 println!(" http://127.0.0.1:8080/health");
131 println!(" http://127.0.0.1:8080/providers");
132 println!(" http://127.0.0.1:8080/providers/worker-management/features/worker_management/operations/list-workers");
133 println!();
134}