summaryrefslogtreecommitdiffstats
path: root/src/api.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/api.rs')
-rw-r--r--src/api.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/api.rs b/src/api.rs
new file mode 100644
index 0000000..e6a91ba
--- /dev/null
+++ b/src/api.rs
@@ -0,0 +1,73 @@
+use std::collections::HashMap;
+
+use axum::{extract::State, response::IntoResponse, Json};
+use serde::{Deserialize, Serialize};
+
+use crate::{service::Services, Check, Error, Status};
+
+pub mod services;
+
+pub fn router() -> axum::Router<Services> {
+ use axum::routing::get;
+
+ axum::Router::new()
+ .route("/healthcheck", get(healthcheck))
+ .merge(services::router())
+ .fallback(fallback)
+}
+
+#[derive(Debug, Clone, Default, Serialize, Deserialize)]
+pub struct Health {
+ pub status: Status,
+ pub output: Option<String>,
+ pub checks: HashMap<String, Check>,
+}
+
+impl<T: std::error::Error> From<T> for Health {
+ fn from(value: T) -> Self {
+ Health {
+ status: Status::Fail,
+ output: Some(value.to_string()),
+ ..Default::default()
+ }
+ }
+}
+
+impl IntoResponse for Health {
+ fn into_response(self) -> axum::response::Response {
+ Json(self).into_response()
+ }
+}
+
+pub async fn healthcheck(State(services): State<Services>) -> Health {
+ let checks = match services.check().await {
+ Ok(c) => c,
+ Err(err) => {
+ return Health {
+ status: Status::Fail,
+ output: Some(err.to_string()),
+ ..Default::default()
+ }
+ }
+ };
+
+ let (status, output) = match checks
+ .values()
+ .filter(|s| !matches!(s.status, Status::Pass))
+ .count()
+ {
+ 0 => (Status::Pass, None),
+ 1 => (Status::Fail, Some("1 issue detected".to_string())),
+ n => (Status::Fail, Some(format!("{n} issues detected"))),
+ };
+
+ Health {
+ status,
+ output,
+ checks,
+ }
+}
+
+pub async fn fallback(uri: axum::http::Uri) -> Error {
+ Error::RouteNotFound(uri)
+}