Major refactor
This commit is contained in:
53
crates/siren-api/src/app.rs
Normal file
53
crates/siren-api/src/app.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use crate::{AppState, error::Result};
|
||||
use axum::Router;
|
||||
use std::{env, sync::Arc};
|
||||
use tokio::net::TcpListener;
|
||||
use tower_http::{
|
||||
cors::{Any, CorsLayer},
|
||||
services::{ServeDir, ServeFile},
|
||||
};
|
||||
|
||||
pub struct App {
|
||||
app_state: AppState,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(app_state: AppState) -> Self {
|
||||
Self { app_state }
|
||||
}
|
||||
|
||||
pub async fn serve(self) -> Result<()> {
|
||||
log::debug!("Starting API...");
|
||||
|
||||
let cors = CorsLayer::new()
|
||||
.allow_origin(Any)
|
||||
.allow_methods(Any)
|
||||
.allow_headers(Any);
|
||||
|
||||
// Serve the built React frontend from frontend/dist (relative to the
|
||||
// working directory). Falls back gracefully if the directory does not
|
||||
// exist yet (e.g. during development when using `npm run dev`).
|
||||
let frontend_dir = env::current_dir()
|
||||
.unwrap_or_default()
|
||||
.join("frontend")
|
||||
.join("dist");
|
||||
|
||||
// For SPA routing: any path not matched by a real file (e.g. /map/<id>)
|
||||
// falls back to index.html so React can handle client-side routing.
|
||||
let index_html = frontend_dir.join("index.html");
|
||||
let serve_dir = ServeDir::new(&frontend_dir).not_found_service(ServeFile::new(index_html));
|
||||
|
||||
let app = Router::new()
|
||||
.nest("/api", crate::get_routes())
|
||||
.fallback_service(serve_dir)
|
||||
.layer(cors)
|
||||
.with_state(Arc::new(self.app_state));
|
||||
|
||||
let api_port: String = env::var("API_PORT").expect("Expected a port in the environment");
|
||||
let addr = format!("0.0.0.0:{}", api_port);
|
||||
|
||||
let listener = TcpListener::bind(&addr).await?;
|
||||
log::info!("API is listening on {}", &addr);
|
||||
Ok(axum::serve(listener, app).await?)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user