[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:
2025-08-20 09:58:21 +02:00
parent 16167d18ff
commit d37daf02f6
12 changed files with 457 additions and 1275 deletions

View 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 = []

View 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();
}

View 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.
}