/
mcmare
/
RustAPI
Обзор
Документация
Войти
/
mcmare
/
RustAPI
Код
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
v0.1.0
server/src/main.rs
77 строк
3 KB
mcmare
Add OpenAPI spec generation and Swagger UI at /docs
18 июл 2026, 16:52
18 июл 2026, 16:52
3cd5502
Код
Авторство
О чём код?
use arc_swap::ArcSwap; use engine::{ build_router, connect_all, docs_router, ensure_tables, hot_reload, load_config, EngineState, RouteTable, ScriptEngine, }; use rustapi_core::{AppState, AuthConfig, HealthCheck, HealthState}; use std::{path::PathBuf, pin::Pin, sync::Arc}; #[tokio::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); let config_dir = std::env::var("CONFIG_DIR").map(PathBuf::from).unwrap_or_else(|_| PathBuf::from("config")); let jwt_secret = std::env::var("JWT_SECRET").map_err(|_| { anyhow::anyhow!("environment variable 'JWT_SECRET' is not set (needed for jwt_sign/jwt_verify in scripts)") })?; let config = load_config(&config_dir)?; tracing::info!( endpoints = config.endpoints.len(), connections = config.connections.len(), "config loaded from {}", config_dir.display() ); let pools = Arc::new(connect_all(&config.connections).await?); ensure_tables(&config.endpoints, &pools).await?; let tokens = load_auth_tokens_or_warn(&config_dir)?; let auth = AuthConfig::new(tokens); let scripts = Arc::new(ScriptEngine::new(pools.clone(), jwt_secret)); let routes = Arc::new(ArcSwap::from_pointee(RouteTable::build(&config)?)); // Keep the watcher alive for the process lifetime — dropping it stops file watching. let _watcher = hot_reload::spawn(config_dir.clone(), routes.clone(), scripts.clone(), pools.clone())?; let engine_state = EngineState { pools: pools.clone(), scripts, routes, }; let endpoints_router = build_router(engine_state.clone(), auth.clone()); let docs = docs_router(engine_state); let health = HealthState::new(health_checks(&pools)); let app_state = AppState { auth, health }; let router = rustapi_core::base_router(app_state).merge(docs).merge(endpoints_router); let router = rustapi_core::common_layers(router); let bind_addr = std::env::var("BIND_ADDR").unwrap_or_else(|_| "127.0.0.1:8080".to_string()); rustapi_core::serve(router, bind_addr.parse()?).await } fn load_auth_tokens_or_warn(config_dir: &std::path::Path) -> anyhow::Result<Vec<String>> { let tokens = engine::config::load_auth_tokens(&config_dir.join("auth.yaml"))?; if tokens.is_empty() { tracing::warn!("no tokens in auth.yaml — every declared endpoint will reject all requests with 401"); } Ok(tokens) } fn health_checks(pools: &Arc<std::collections::HashMap<String, engine::DbPool>>) -> Vec<HealthCheck> { pools .iter() .map(|(name, pool)| { let name = name.clone(); let pool = pool.clone(); Arc::new(move || { let name = name.clone(); let pool = pool.clone(); Box::pin(async move { (name, pool.ping().await) }) as Pin<Box<dyn std::future::Future<Output = (String, bool)> + Send>> }) as HealthCheck }) .collect() }