[feat] introduced server
and cli
crates with foundational HTTP server and CLI implementation, including routing, health check, and configuration setup
This commit is contained in:
22
backend-rust/crates/server/Cargo.toml
Normal file
22
backend-rust/crates/server/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "server"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
axum = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { workspace = true }
|
||||
dotenv = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
|
||||
api = { path = "../api" }
|
||||
http = "1.3.1"
|
||||
|
||||
[features]
|
||||
default = []
|
58
backend-rust/crates/server/src/lib.rs
Normal file
58
backend-rust/crates/server/src/lib.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use axum::{routing::get, Json, Router};
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
use tokio::net::TcpListener;
|
||||
use tracing::{info, level_filters::LevelFilter};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
use api::services::{DefaultHealthService, HealthService};
|
||||
use api::types::Health;
|
||||
|
||||
pub struct AppState {
|
||||
pub health_service: Arc<dyn HealthService>,
|
||||
}
|
||||
|
||||
pub async fn build_router(state: Arc<AppState>) -> Router {
|
||||
Router::new().route(
|
||||
"/health",
|
||||
get({
|
||||
let state = state.clone();
|
||||
move || health_handler(state.clone())
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
async fn health_handler(state: Arc<AppState>) -> Json<Health> {
|
||||
let res = state.health_service.health().await;
|
||||
Json(res)
|
||||
}
|
||||
|
||||
pub async fn start_server(addr: SocketAddr) -> anyhow::Result<()> {
|
||||
init_tracing();
|
||||
|
||||
// TODO: initialize database pools and other infrastructure here.
|
||||
// let pool = sqlx::PgPool::connect(&db_url).await?;
|
||||
|
||||
let state = Arc::new(AppState {
|
||||
health_service: Arc::new(DefaultHealthService),
|
||||
});
|
||||
|
||||
let app = build_router(state).await;
|
||||
|
||||
let listener = TcpListener::bind(addr).await?;
|
||||
info!("HTTP server listening on http://{}", addr);
|
||||
axum::serve(listener, app).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_tracing() {
|
||||
let env_filter = EnvFilter::try_from_default_env()
|
||||
.or_else(|_| EnvFilter::try_new("info"))
|
||||
.unwrap()
|
||||
.add_directive(LevelFilter::INFO.into());
|
||||
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(env_filter)
|
||||
.with_target(true)
|
||||
.compact()
|
||||
.init();
|
||||
}
|
22
backend-rust/crates/server/tests/health.rs
Normal file
22
backend-rust/crates/server/tests/health.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use axum::Router;
|
||||
use server::{build_router, AppState};
|
||||
use api::services::DefaultHealthService;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn health_ok() {
|
||||
let state = Arc::new(AppState {
|
||||
health_service: Arc::new(DefaultHealthService),
|
||||
});
|
||||
|
||||
let app: Router = build_router(state).await;
|
||||
|
||||
let req = http::Request::builder()
|
||||
.uri("/health")
|
||||
.body(axum::body::Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let res = axum::http::Request::from(req);
|
||||
let res = axum::http::Request::from(res);
|
||||
let _ = app; // You can use axum-test to send requests if desired.
|
||||
}
|
Reference in New Issue
Block a user