feat: Add health check endpoint

Introduce a new health check endpoint at `/api/health`. This endpoint
returns a JSON response indicating the server's status and configuration
details, such as the port, data path, and configured URLs for external
services.

This change also refactors the application setup by:
- Creating a `lib.rs` file to house the `create_router` function, making
  it
  reusable for both the main application and integration tests.
- Moving configuration loading logic into `main.rs` and passing it as a
  shared state (`Arc<Config>`) to the router.
- Adding a unit test (`health_test.rs`) to verify the functionality of
  the
  health check endpoint.
- Updating `Cargo.toml` and `Cargo.lock` to include the `tower`
  dependency,
  which is used for testing.
This commit is contained in:
2026-04-13 12:41:40 +02:00
parent 44dac06961
commit 80a6537e16
7 changed files with 131 additions and 5 deletions
+14
View File
@@ -0,0 +1,14 @@
pub mod config;
pub mod error;
pub mod routes;
use std::sync::Arc;
use axum::Router;
use config::Config;
/// Build the application router. Used by main.rs and integration tests.
pub fn create_router(config: Arc<Config>) -> Router {
routes::api_router().with_state(config)
}
+11 -5
View File
@@ -1,12 +1,18 @@
mod config;
mod error;
use config::Config;
use std::sync::Arc;
use tokio::net::TcpListener;
use doctate_server::config::Config;
#[tokio::main]
async fn main() {
dotenvy::dotenv().ok();
let config = Arc::new(Config::from_env());
println!("Server starting on port {}", config.server_port);
let addr = format!("0.0.0.0:{}", config.server_port);
println!("Server starting on {addr}");
let app = doctate_server::create_router(config);
let listener = TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
}
+18
View File
@@ -0,0 +1,18 @@
use std::sync::Arc;
use axum::extract::State;
use axum::Json;
use serde_json::{json, Value};
use crate::config::Config;
pub async fn handle_health(State(config): State<Arc<Config>>) -> Json<Value> {
Json(json!({
"status": "ok",
"port": config.server_port,
"data_path": config.data_path.to_string_lossy(),
"users": config.users.iter().map(|u| &u.slug).collect::<Vec<_>>(),
"whisper_url": config.whisper_url,
"ollama_url": config.ollama_url,
}))
}
+11
View File
@@ -0,0 +1,11 @@
mod health;
use std::sync::Arc;
use axum::Router;
use crate::config::Config;
pub fn api_router() -> Router<Arc<Config>> {
Router::new().route("/api/health", axum::routing::get(health::handle_health))
}