1use crate::health::{HealthCheck, HealthStatus};
2use std::sync::Arc;
3
4pub struct HealthEndpoint {
9 pub(crate) check: Arc<dyn HealthCheck>,
10}
11
12impl HealthEndpoint {
13 pub fn new(check: impl HealthCheck + 'static) -> Self {
15 Self {
16 check: Arc::new(check),
17 }
18 }
19
20 pub fn get_status_json(&self) -> String {
22 let status = self.check.check_health();
23 let message = self.check.status_message();
24
25 let status_str = match status {
26 HealthStatus::Healthy => "healthy",
27 HealthStatus::Degraded { .. } => "degraded",
28 HealthStatus::Unhealthy { .. } => "unhealthy",
29 };
30
31 format!(
32 "{{\"status\":\"{}\",\"message\":\"{}\"}}",
33 status_str,
34 message.replace('"', "\\\"")
35 )
36 }
37
38 pub fn get_http_status_code(&self) -> u16 {
40 match self.check.check_health() {
41 HealthStatus::Healthy => 200,
42 HealthStatus::Degraded { .. } => 200, HealthStatus::Unhealthy { .. } => 503,
44 }
45 }
46}
47
48#[cfg(feature = "http")]
49mod axum_integration {
50 use super::*;
51 use axum::{Json, http::StatusCode, response::IntoResponse};
52 use serde::Serialize;
53
54 #[derive(Serialize)]
55 struct HealthResponse {
56 status: String,
57 message: String,
58 }
59
60 impl IntoResponse for HealthEndpoint {
61 fn into_response(self) -> axum::response::Response {
62 let status = self.check.check_health();
63 let message = self.check.status_message();
64
65 let (code, status_str) = match status {
66 HealthStatus::Healthy => (StatusCode::OK, "healthy"),
67 HealthStatus::Degraded { .. } => (StatusCode::OK, "degraded"),
68 HealthStatus::Unhealthy { .. } => (StatusCode::SERVICE_UNAVAILABLE, "unhealthy"),
69 };
70
71 let body = Json(HealthResponse {
72 status: status_str.to_string(),
73 message,
74 });
75
76 (code, body).into_response()
77 }
78 }
79}