97 lines
3.0 KiB
Rust
97 lines
3.0 KiB
Rust
/// Cookie and JWT authentication utilities
|
|
mod cookie;
|
|
/// Environment configuration loading
|
|
mod env;
|
|
/// HTTP request handlers for all endpoints
|
|
mod handlers;
|
|
/// Data structures for request/response serialization
|
|
mod models;
|
|
/// Axum router configuration with all routes and middleware
|
|
mod router;
|
|
|
|
use std::sync::Arc;
|
|
|
|
use axum::http::{
|
|
HeaderValue, Method,
|
|
header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE},
|
|
};
|
|
use dotenv::dotenv;
|
|
use router::create_router;
|
|
use sqlx::{PgPool, postgres::PgPoolOptions};
|
|
use tower_http::cors::CorsLayer;
|
|
|
|
use crate::env::Env;
|
|
|
|
/// Shared application state passed to all route handlers.
|
|
///
|
|
/// Contains the database connection pool and environment configuration.
|
|
/// This is wrapped in Arc for thread-safe sharing across async tasks and cloned into each route
|
|
/// via `with_state`.
|
|
///
|
|
/// # Fields
|
|
/// - `db`: PostgreSQL connection pool for database access (via `sqlx::PgPool`)
|
|
/// - `env`: [`Env`] configuration loaded from environment variables
|
|
pub struct AppState {
|
|
db: PgPool,
|
|
env: Env,
|
|
}
|
|
|
|
/// Main application entry point.
|
|
///
|
|
/// Initializes the server by:
|
|
/// 1. Loading environment variables from `.env` file
|
|
/// 2. Establishing database connection pool to PostgreSQL
|
|
/// 3. Configuring CORS policy for cross-origin requests
|
|
/// 4. Creating the router with [`create_router`] containing all endpoints
|
|
/// 5. Starting HTTP server on port 8001
|
|
///
|
|
/// # Server Configuration
|
|
/// - Binds to `0.0.0.0:8001` (all network interfaces)
|
|
/// - Allows: GET, POST, PATCH, DELETE methods
|
|
/// - Allows credentials and custom headers
|
|
/// - CORS origin configured from [`Env`]
|
|
///
|
|
/// # State Setup
|
|
/// Creates shared [`AppState`] wrapped in `Arc` and passes to all routes
|
|
///
|
|
/// # Panics
|
|
/// - If environment loading fails
|
|
/// - If database connection fails
|
|
#[tokio::main]
|
|
async fn main() {
|
|
dotenv().ok();
|
|
let env = Env::load();
|
|
let database_url = &env.db_url;
|
|
|
|
// Establish connection pool to PostgreSQL
|
|
let pool = match PgPoolOptions::new().connect(database_url).await {
|
|
Ok(pool) => {
|
|
println!("Database connection successful");
|
|
pool
|
|
}
|
|
Err(err) => {
|
|
println!("Failed to connect to database: {:?}", err);
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
// Configure CORS to allow requests from frontend
|
|
let cors = CorsLayer::new()
|
|
.allow_origin(env.origin.parse::<HeaderValue>().unwrap())
|
|
.allow_methods([Method::GET, Method::POST, Method::PATCH, Method::DELETE])
|
|
.allow_credentials(true)
|
|
.allow_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE]);
|
|
|
|
// Build router with all endpoints and apply CORS middleware
|
|
let app = create_router(Arc::new(AppState {
|
|
db: pool.clone(),
|
|
env: env.clone(),
|
|
}))
|
|
.layer(cors);
|
|
|
|
// Start listening for incoming connections
|
|
let uri = format!("0.0.0.0:{}", env.backend_port);
|
|
let listener = tokio::net::TcpListener::bind(&uri).await.unwrap();
|
|
let _ = axum::serve(listener, app).await;
|
|
}
|