Initial commit: FunConnect project with server, relay, client and admin panel
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
79
server/src/main.rs
Normal file
79
server/src/main.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use anyhow::Result;
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use std::sync::Arc;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use tower_http::services::ServeDir;
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
||||
mod api;
|
||||
mod auth_middleware;
|
||||
mod db;
|
||||
mod presence;
|
||||
mod relay;
|
||||
mod signaling;
|
||||
mod state;
|
||||
|
||||
pub use state::AppState;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
dotenvy::dotenv().ok();
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(tracing_subscriber::EnvFilter::new(
|
||||
std::env::var("RUST_LOG").unwrap_or_else(|_| "funmc_server=debug,tower_http=info".into()),
|
||||
))
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.init();
|
||||
|
||||
let database_url = std::env::var("DATABASE_URL")
|
||||
.unwrap_or_else(|_| "postgres://postgres:password@localhost/funmc".into());
|
||||
|
||||
let pool = PgPoolOptions::new()
|
||||
.max_connections(10)
|
||||
.connect(&database_url)
|
||||
.await?;
|
||||
|
||||
sqlx::migrate!("./migrations").run(&pool).await?;
|
||||
|
||||
let jwt_secret = std::env::var("JWT_SECRET")
|
||||
.unwrap_or_else(|_| "dev-secret-change-in-production".into());
|
||||
|
||||
let state = Arc::new(AppState::new(pool, jwt_secret.clone()));
|
||||
|
||||
// Start QUIC relay server in background
|
||||
let jwt_for_relay = jwt_secret.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = relay::server::RelayServer::start(jwt_for_relay).await {
|
||||
tracing::error!("QUIC relay server error: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
let cors = CorsLayer::new()
|
||||
.allow_origin(Any)
|
||||
.allow_methods(Any)
|
||||
.allow_headers(Any);
|
||||
|
||||
// Admin panel static files (default to dist directory for production)
|
||||
let admin_dir = std::env::var("ADMIN_PANEL_DIR").unwrap_or_else(|_| "./admin-panel/dist".into());
|
||||
|
||||
let app = axum::Router::new()
|
||||
.nest("/api/v1", api::router(state.clone()))
|
||||
.nest("/download", api::download_router())
|
||||
.nest_service("/admin", ServeDir::new(&admin_dir).append_index_html_on_directories(true))
|
||||
.layer(TraceLayer::new_for_http())
|
||||
.layer(cors)
|
||||
.with_state(state);
|
||||
|
||||
let addr = std::env::var("LISTEN_ADDR").unwrap_or_else(|_| "0.0.0.0:3000".into());
|
||||
tracing::info!("HTTP API listening on {}", addr);
|
||||
tracing::info!("Admin panel at http://{}/admin", addr);
|
||||
tracing::info!("Download page at http://{}/download", addr);
|
||||
tracing::info!("QUIC relay listening on port 3001");
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||
axum::serve(listener, app).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user