1use axum::{
2 http::StatusCode,
3 response::{IntoResponse, Response},
4 Json,
5};
6use serde::Serialize;
7
8#[derive(Debug, Clone, Serialize)]
25pub struct HealthResponse {
26 pub status: &'static str,
27 #[serde(skip)]
28 status_code: StatusCode,
29}
30
31impl HealthResponse {
32 pub const fn ok() -> Self {
34 Self {
35 status: "ok",
36 status_code: StatusCode::OK,
37 }
38 }
39
40 pub const fn degraded() -> Self {
45 Self {
46 status: "degraded",
47 status_code: StatusCode::OK,
48 }
49 }
50
51 pub const fn unhealthy() -> Self {
56 Self {
57 status: "unhealthy",
58 status_code: StatusCode::SERVICE_UNAVAILABLE,
59 }
60 }
61}
62
63impl IntoResponse for HealthResponse {
64 fn into_response(self) -> Response {
65 (self.status_code, Json(self)).into_response()
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn ok_has_correct_status() {
75 let r = HealthResponse::ok();
76 assert_eq!(r.status, "ok");
77 assert_eq!(r.status_code, StatusCode::OK);
78 }
79
80 #[test]
81 fn degraded_has_correct_status() {
82 let r = HealthResponse::degraded();
83 assert_eq!(r.status, "degraded");
84 assert_eq!(r.status_code, StatusCode::OK);
85 }
86
87 #[test]
88 fn unhealthy_has_correct_status() {
89 let r = HealthResponse::unhealthy();
90 assert_eq!(r.status, "unhealthy");
91 assert_eq!(r.status_code, StatusCode::SERVICE_UNAVAILABLE);
92 }
93
94 #[test]
95 fn serializes_status_field_only() {
96 let r = HealthResponse::ok();
97 let v = serde_json::to_value(&r).unwrap();
98 assert_eq!(v["status"], "ok");
99 assert!(v.get("status_code").is_none());
100 }
101}