taceo-nodes-common 0.4.4

Collection of common functions used by nodes in our MPC networks
Documentation
//! Health Check Endpoints
//!
//! This module defines the health and version endpoints.
//! - `/health` – general health check
//! - `/version` – version information about the service
//!
//! The endpoints include a `Cache-Control: no-cache` header to prevent caching of responses.

use axum::{
    Router,
    http::{HeaderValue, StatusCode, header},
    response::IntoResponse,
    routing::get,
};
use tower_http::set_header::SetResponseHeaderLayer;

use crate::StartedServices;

/// Creates a router exposing `/health` and `/version`.
///
/// The `/health` endpoint reports healthy only if all registered [`StartedServices`] have started.
///
/// All responses have `Cache-Control: no-cache` set.
pub fn routes_with_services<S>(started_services: StartedServices, version_str: String) -> Router<S>
where
    S: Clone + Send + Sync + 'static,
{
    Router::new()
        .route("/health", get(move || async { health(started_services) }))
        .route("/version", get(move || async { version(version_str) }))
        .layer(SetResponseHeaderLayer::overriding(
            header::CACHE_CONTROL,
            HeaderValue::from_static("no-cache"),
        ))
}

/// Creates a router exposing `/health` and `/version`.
///
/// The `/health` endpoint always returns `200 OK` which basically just signals that the axum server did start successfully.
///
/// All responses have `Cache-Control: no-cache` set.
pub fn routes<S>(version_str: String) -> Router<S>
where
    S: Clone + Send + Sync + 'static,
{
    Router::new()
        .route(
            "/health",
            get(|| async move { (StatusCode::OK, "healthy") }),
        )
        .route("/version", get(move || async { version(version_str) }))
        .layer(SetResponseHeaderLayer::overriding(
            header::CACHE_CONTROL,
            HeaderValue::from_static("no-cache"),
        ))
}

/// General health check endpoint.
///
/// Returns `200 OK` with a plain `"healthy"` response if all services already started.
/// Returns `503 Service Unavailable` with a plain `"starting"`response if one of the services did not start yet.
fn health(started_services: StartedServices) -> impl IntoResponse {
    if started_services.all_started() {
        (StatusCode::OK, "healthy")
    } else {
        (StatusCode::SERVICE_UNAVAILABLE, "starting")
    }
}

/// Responds with cargo package name, cargo package version, and the git hash of the repository that was used to build the binary.
///
/// Returns `200 OK` with a string response.
fn version(version_str: String) -> impl IntoResponse {
    (StatusCode::OK, version_str)
}