use axum::{
http::StatusCode,
response::{IntoResponse, Response},
Json,
};
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub struct HealthResponse {
pub status: &'static str,
#[serde(skip)]
status_code: StatusCode,
}
impl HealthResponse {
pub const fn ok() -> Self {
Self {
status: "ok",
status_code: StatusCode::OK,
}
}
pub const fn degraded() -> Self {
Self {
status: "degraded",
status_code: StatusCode::OK,
}
}
pub const fn unhealthy() -> Self {
Self {
status: "unhealthy",
status_code: StatusCode::SERVICE_UNAVAILABLE,
}
}
}
impl IntoResponse for HealthResponse {
fn into_response(self) -> Response {
(self.status_code, Json(self)).into_response()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ok_has_correct_status() {
let r = HealthResponse::ok();
assert_eq!(r.status, "ok");
assert_eq!(r.status_code, StatusCode::OK);
}
#[test]
fn degraded_has_correct_status() {
let r = HealthResponse::degraded();
assert_eq!(r.status, "degraded");
assert_eq!(r.status_code, StatusCode::OK);
}
#[test]
fn unhealthy_has_correct_status() {
let r = HealthResponse::unhealthy();
assert_eq!(r.status, "unhealthy");
assert_eq!(r.status_code, StatusCode::SERVICE_UNAVAILABLE);
}
#[test]
fn serializes_status_field_only() {
let r = HealthResponse::ok();
let v = serde_json::to_value(&r).unwrap();
assert_eq!(v["status"], "ok");
assert!(v.get("status_code").is_none());
}
}