feat: rust project initialization

This commit is contained in:
2025-12-21 18:19:21 +01:00
commit d5a2859b64
28 changed files with 4555 additions and 0 deletions

38
src/route/health.rs Normal file
View File

@@ -0,0 +1,38 @@
//! Health check endpoint for monitoring service availability.
use poem_openapi::{ApiResponse, OpenApi};
use super::ApiCategory;
#[derive(ApiResponse)]
enum HealthResponse {
/// Success
#[oai(status = 200)]
Ok,
/// Too Many Requests - rate limit exceeded
#[oai(status = 429)]
#[allow(dead_code)]
TooManyRequests,
}
/// Health check API for monitoring service availability.
#[derive(Default, Clone)]
pub struct HealthApi;
#[OpenApi(tag = "ApiCategory::Health")]
impl HealthApi {
#[oai(path = "/health", method = "get")]
async fn ping(&self) -> HealthResponse {
tracing::event!(target: "backend::health", tracing::Level::DEBUG, "Accessing health-check endpoint");
HealthResponse::Ok
}
}
#[tokio::test]
async fn health_check_works() {
let app = crate::get_test_app();
let cli = poem::test::TestClient::new(app);
let resp = cli.get("/api/health").send().await;
resp.assert_status_is_ok();
resp.assert_text("").await;
}

86
src/route/meta.rs Normal file
View File

@@ -0,0 +1,86 @@
//! Application metadata endpoint for retrieving version and name information.
use poem::Result;
use poem_openapi::{ApiResponse, Object, OpenApi, payload::Json};
use super::ApiCategory;
use crate::settings::ApplicationSettings;
#[derive(Object, Debug, Clone, serde::Serialize, serde::Deserialize)]
struct Meta {
version: String,
name: String,
}
impl From<&MetaApi> for Meta {
fn from(value: &MetaApi) -> Self {
let version = value.version.clone();
let name = value.name.clone();
Self { version, name }
}
}
#[derive(ApiResponse)]
enum MetaResponse {
/// Success
#[oai(status = 200)]
Meta(Json<Meta>),
/// Too Many Requests - rate limit exceeded
#[oai(status = 429)]
#[allow(dead_code)]
TooManyRequests,
}
/// API for retrieving application metadata (name and version).
#[derive(Clone)]
pub struct MetaApi {
name: String,
version: String,
}
impl From<&ApplicationSettings> for MetaApi {
fn from(value: &ApplicationSettings) -> Self {
let name = value.name.clone();
let version = value.version.clone();
Self { name, version }
}
}
#[OpenApi(tag = "ApiCategory::Meta")]
impl MetaApi {
#[oai(path = "/meta", method = "get")]
async fn meta(&self) -> Result<MetaResponse> {
tracing::event!(target: "backend::meta", tracing::Level::DEBUG, "Accessing meta endpoint");
Ok(MetaResponse::Meta(Json(self.into())))
}
}
#[cfg(test)]
mod tests {
#[tokio::test]
async fn meta_endpoint_returns_correct_data() {
let app = crate::get_test_app();
let cli = poem::test::TestClient::new(app);
let resp = cli.get("/api/meta").send().await;
resp.assert_status_is_ok();
let json_value: serde_json::Value = resp.json().await.value().deserialize();
assert!(
json_value.get("version").is_some(),
"Response should have version field"
);
assert!(
json_value.get("name").is_some(),
"Response should have name field"
);
}
#[tokio::test]
async fn meta_endpoint_returns_200_status() {
let app = crate::get_test_app();
let cli = poem::test::TestClient::new(app);
let resp = cli.get("/api/meta").send().await;
resp.assert_status_is_ok();
}
}

37
src/route/mod.rs Normal file
View File

@@ -0,0 +1,37 @@
//! API route handlers for the backend server.
//!
//! This module contains all the HTTP endpoint handlers organized by functionality:
//! - Health checks
//! - Application metadata
use poem_openapi::Tags;
mod health;
mod meta;
use crate::settings::Settings;
#[derive(Tags)]
enum ApiCategory {
Health,
Meta,
}
pub(crate) struct Api {
health: health::HealthApi,
meta: meta::MetaApi,
}
impl From<&Settings> for Api {
fn from(value: &Settings) -> Self {
let health = health::HealthApi;
let meta = meta::MetaApi::from(&value.application);
Self { health, meta }
}
}
impl Api {
pub fn apis(self) -> (health::HealthApi, meta::MetaApi) {
(self.health, self.meta)
}
}