hoprd_api/
checks.rs

1use axum::{extract::State, http::status::StatusCode, response::IntoResponse};
2use std::sync::Arc;
3
4use hopr_lib::HoprState;
5
6use crate::AppState;
7
8/// Check whether the node is started.
9#[utoipa::path(
10        get,
11        path = "/startedz",
12        responses(
13            (status = 200, description = "The node is started and running"),
14            (status = 412, description = "The node is not started and running"),
15        ),
16        tag = "Checks"
17    )]
18pub(super) async fn startedz(State(state): State<Arc<AppState>>) -> impl IntoResponse {
19    is_running(state) // FIXME: improve this once node state granularity is improved
20}
21
22/// Check whether the node is ready to accept connections.
23#[utoipa::path(
24        get,
25        path = "/readyz",
26        responses(
27            (status = 200, description = "The node is ready to accept connections"),
28            (status = 412, description = "The node is not ready to accept connections"),
29        ),
30        tag = "Checks"
31    )]
32pub(super) async fn readyz(State(state): State<Arc<AppState>>) -> impl IntoResponse {
33    is_running(state) // FIXME: improve this once node state granularity is improved
34}
35
36/// Check whether the node is healthy.
37#[utoipa::path(
38        get,
39        path = "/healthyz",
40        responses(
41            (status = 200, description = "The node is healthy"),
42            (status = 412, description = "The node is not healthy"),
43        ),
44        tag = "Checks"
45    )]
46pub(super) async fn healthyz(State(state): State<Arc<AppState>>) -> impl IntoResponse {
47    is_running(state) // FIXME: improve this once node state granularity is improved
48}
49
50fn is_running(state: Arc<AppState>) -> impl IntoResponse {
51    match state.hopr.status() {
52        HoprState::Running => (StatusCode::OK, "").into_response(),
53        _ => (StatusCode::PRECONDITION_FAILED, "").into_response(),
54    }
55}
56/// Check whether the node is eligible in the network.
57#[utoipa::path(
58        get,
59        path = "/eligiblez",
60        responses(
61            (status = 200, description = "The node is allowed in the network"),
62            (status = 412, description = "The node is not allowed in the network"),
63            (status = 500, description = "Internal server error"),
64        ),
65        tag = "Checks"
66    )]
67pub(super) async fn eligiblez(State(state): State<Arc<AppState>>) -> impl IntoResponse {
68    let hopr = state.hopr.clone();
69
70    match hopr.get_eligibility_status().await {
71        Ok(true) => (StatusCode::OK, "").into_response(),
72        Ok(false) => (StatusCode::PRECONDITION_FAILED, "Node not eligible").into_response(),
73        Err(hopr_lib::errors::HoprLibError::ChainApi(e)) => {
74            // The "division by zero" error is caused by the self-registration,
75            // which is forbidden to the public and thus returns false
76            // therefore the eligibility check should be ignored
77            let err_str = e.to_string();
78            if err_str.to_lowercase().contains("division or modulo by zero") {
79                (StatusCode::PRECONDITION_FAILED, "Node not eligible").into_response()
80            } else {
81                (StatusCode::INTERNAL_SERVER_ERROR, err_str).into_response()
82            }
83        }
84        Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
85    }
86}