From c6ef37d5a76e15d58b3db3c543c92daa5a3ba322 Mon Sep 17 00:00:00 2001 From: cxymds Date: Thu, 25 Jun 2026 09:37:57 +0800 Subject: [PATCH] fix(server): handle MinIO cluster health probe (#3833) --- rustfs/src/server/compress.rs | 2 ++ rustfs/src/server/layer.rs | 33 ++++++++++++++++++++++++++++++--- rustfs/src/server/mod.rs | 6 +++--- rustfs/src/server/prefix.rs | 3 +++ rustfs/src/server/readiness.rs | 1 + 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/rustfs/src/server/compress.rs b/rustfs/src/server/compress.rs index 9dc975d50..d92d06e68 100644 --- a/rustfs/src/server/compress.rs +++ b/rustfs/src/server/compress.rs @@ -422,6 +422,7 @@ impl PathCategory { || path.starts_with("/health/") || path == "/minio/health/live" || path == "/minio/health/ready" + || path == "/minio/health/cluster" { PathCategory::Probe } else { @@ -772,6 +773,7 @@ mod tests { assert_eq!(PathCategory::classify("/health/ready"), PathCategory::Probe); assert_eq!(PathCategory::classify("/minio/health/live"), PathCategory::Probe); assert_eq!(PathCategory::classify("/minio/health/ready"), PathCategory::Probe); + assert_eq!(PathCategory::classify("/minio/health/cluster"), PathCategory::Probe); } #[test] diff --git a/rustfs/src/server/layer.rs b/rustfs/src/server/layer.rs index 800ba7a41..3983b6198 100644 --- a/rustfs/src/server/layer.rs +++ b/rustfs/src/server/layer.rs @@ -21,8 +21,9 @@ use crate::server::cors; use crate::server::hybrid::HybridBody; use crate::server::{ ADMIN_PREFIX, CONSOLE_PREFIX, HEALTH_COMPAT_LIVE_PATH, HEALTH_PREFIX, HEALTH_READY_PATH, MINIO_ADMIN_PREFIX, - MINIO_ADMIN_V3_PREFIX, MINIO_HEALTH_LIVE_PATH, MINIO_HEALTH_READY_PATH, RPC_PREFIX, RUSTFS_ADMIN_PREFIX, - active_http_requests, collect_dependency_readiness_report, has_path_prefix, is_admin_path, is_table_catalog_path, + MINIO_ADMIN_V3_PREFIX, MINIO_HEALTH_CLUSTER_PATH, MINIO_HEALTH_LIVE_PATH, MINIO_HEALTH_READY_PATH, RPC_PREFIX, + RUSTFS_ADMIN_PREFIX, active_http_requests, collect_dependency_readiness_report, has_path_prefix, is_admin_path, + is_table_catalog_path, }; use crate::storage::apply_cors_headers; use crate::storage::request_context::{ @@ -885,7 +886,7 @@ fn resolve_public_health_probe(method: &Method, path: &str) -> Option Some(HealthProbe::Liveness), - HEALTH_READY_PATH | MINIO_HEALTH_READY_PATH => Some(HealthProbe::Readiness), + HEALTH_READY_PATH | MINIO_HEALTH_READY_PATH | MINIO_HEALTH_CLUSTER_PATH => Some(HealthProbe::Readiness), _ => None, } } @@ -1291,6 +1292,7 @@ impl ConditionalCorsLayer { "/health/ready", "/minio/health/live", "/minio/health/ready", + "/minio/health/cluster", "/profile/cpu", "/profile/memory", ]; @@ -1925,6 +1927,31 @@ mod tests { .await; } + #[tokio::test] + #[serial] + async fn public_health_endpoint_layer_handles_minio_health_cluster_before_inner_service() { + async_with_vars([(rustfs_config::ENV_HEALTH_ENDPOINT_ENABLE, Some("true"))], async { + let inner = CountingHybridService::default(); + let calls = inner.calls(); + let mut service = PublicHealthEndpointLayer.layer(inner); + + let response = service + .call( + Request::builder() + .method(Method::GET) + .uri(MINIO_HEALTH_CLUSTER_PATH) + .body(Full::::from(Bytes::new())) + .expect("request"), + ) + .await + .expect("health response"); + + assert!(response.status() == StatusCode::OK || response.status() == StatusCode::SERVICE_UNAVAILABLE); + assert_eq!(calls.load(Ordering::SeqCst), 0); + }) + .await; + } + #[tokio::test] #[serial] async fn public_health_endpoint_layer_forwards_unknown_health_path_when_endpoint_disabled() { diff --git a/rustfs/src/server/mod.rs b/rustfs/src/server/mod.rs index fe0765749..b8566e80f 100644 --- a/rustfs/src/server/mod.rs +++ b/rustfs/src/server/mod.rs @@ -51,9 +51,9 @@ pub(crate) use module_switch::{ }; pub(crate) use prefix::{ ADMIN_PREFIX, CONSOLE_PREFIX, FAVICON_PATH, HEALTH_COMPAT_LIVE_PATH, HEALTH_PREFIX, HEALTH_READY_PATH, LICENSE, - MINIO_ADMIN_PREFIX, MINIO_ADMIN_V3_PREFIX, MINIO_HEALTH_LIVE_PATH, MINIO_HEALTH_READY_PATH, PROFILE_CPU_PATH, - PROFILE_MEMORY_PATH, RPC_PREFIX, RUSTFS_ADMIN_PREFIX, TABLE_CATALOG_COMPAT_PREFIX, TABLE_CATALOG_PREFIX, TONIC_PREFIX, - VERSION, has_path_prefix, is_admin_path, is_table_catalog_path, + MINIO_ADMIN_PREFIX, MINIO_ADMIN_V3_PREFIX, MINIO_HEALTH_CLUSTER_PATH, MINIO_HEALTH_LIVE_PATH, MINIO_HEALTH_READY_PATH, + PROFILE_CPU_PATH, PROFILE_MEMORY_PATH, RPC_PREFIX, RUSTFS_ADMIN_PREFIX, TABLE_CATALOG_COMPAT_PREFIX, TABLE_CATALOG_PREFIX, + TONIC_PREFIX, VERSION, has_path_prefix, is_admin_path, is_table_catalog_path, }; pub(crate) use readiness::DependencyReadiness; pub(crate) use readiness::DependencyReadinessReport; diff --git a/rustfs/src/server/prefix.rs b/rustfs/src/server/prefix.rs index b4e6cb3ad..a32d76b51 100644 --- a/rustfs/src/server/prefix.rs +++ b/rustfs/src/server/prefix.rs @@ -40,6 +40,9 @@ pub(crate) const MINIO_HEALTH_LIVE_PATH: &str = "/minio/health/live"; /// MinIO-compatible health readiness probe alias path. pub(crate) const MINIO_HEALTH_READY_PATH: &str = "/minio/health/ready"; +/// MinIO-compatible cluster health probe alias path. +pub(crate) const MINIO_HEALTH_CLUSTER_PATH: &str = "/minio/health/cluster"; + /// Predefined administrative prefix for RustFS server routes. /// This prefix is used for endpoints that handle administrative tasks /// such as configuration, monitoring, and management. diff --git a/rustfs/src/server/readiness.rs b/rustfs/src/server/readiness.rs index 581c0e456..da6b6541b 100644 --- a/rustfs/src/server/readiness.rs +++ b/rustfs/src/server/readiness.rs @@ -139,6 +139,7 @@ fn is_probe_path(path: &str) -> bool { | crate::server::HEALTH_READY_PATH | crate::server::MINIO_HEALTH_LIVE_PATH | crate::server::MINIO_HEALTH_READY_PATH + | crate::server::MINIO_HEALTH_CLUSTER_PATH | crate::server::FAVICON_PATH );