Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
241 changes: 241 additions & 0 deletions backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ tokio = { version = "1", features = ["full"] }
tower = "0.4"
http = "1"
serde_json = "1"
tower-http = { version = "0.6.8", features = ["cors"] }
dotenvy = "0.15"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
Expand Down
59 changes: 58 additions & 1 deletion backend/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! # predifi-backend
//!
//! A minimal Axum HTTP server with CORS and request-logging middleware.
//! A minimal Axum HTTP server that demonstrates the request-logging middleware
//! and a versioned API router layout.
//!
Expand All @@ -22,10 +23,64 @@ pub mod request_logger;
pub mod routes;

use axum::{routing::get, Json, Router};
use http::HeaderValue;
use config::Config;
use request_logger::LoggingLayer;
use routes::v1;
use serde_json::json;
use tower_http::cors::{AllowOrigin, CorsLayer};

/// Allowed frontend origins for CORS.
///
/// Add any additional frontend URLs here.
/// In production, replace with your actual deployed frontend URL.
const ALLOWED_ORIGINS: &[&str] = &[
"http://localhost:3000",
"http://localhost:5173",
"https://predifi.app",
];

/// Build the CORS middleware layer.
///
/// Only requests from the origins listed in `ALLOWED_ORIGINS` are permitted.
/// All other origins will be rejected by the browser.
pub fn build_cors() -> CorsLayer {
let origins: Vec<HeaderValue> = ALLOWED_ORIGINS
.iter()
.filter_map(|origin| origin.parse().ok())
.collect();

CorsLayer::new()
.allow_origin(AllowOrigin::list(origins))
.allow_methods([
http::Method::GET,
http::Method::POST,
http::Method::PUT,
http::Method::DELETE,
http::Method::OPTIONS,
])
.allow_headers([
http::header::CONTENT_TYPE,
http::header::AUTHORIZATION,
http::header::ACCEPT,
])
}

/// Health-check handler.
///
/// Returns HTTP 200 with basic system info:
/// - `status`: always `"ok"` when the server is running
/// - `service`: name of the service
/// - `version`: current package version from Cargo.toml
async fn health() -> Json<serde_json::Value> {
Json(json!({
"status": "ok",
"service": "predifi-backend",
"version": env!("CARGO_PKG_VERSION")
}))
}

/// Root handler — returns a welcome message.
use tracing::{error, info};
use tracing_subscriber::EnvFilter;

Expand All @@ -52,13 +107,15 @@ async fn root() -> Json<serde_json::Value> {
}))
}

/// Build the Axum router with the logging middleware attached.
/// Build the Axum router with CORS and logging middleware attached.
///
/// Keeping router construction in its own function makes it easy to reuse
/// in tests without binding to a real TCP port.
pub fn build_router() -> Router {
Router::new()
.route("/", get(root))
.route("/health", get(health))
.layer(build_cors())
.route("/health", get(v1::health))
.nest("/api", routes::router())
.layer(LoggingLayer)
Expand Down
Loading
Loading