fix(server): add MinIO health endpoint aliases (#3724)

This commit is contained in:
houseme
2026-06-22 13:53:38 +08:00
committed by GitHub
parent ed45d1be2d
commit 2c500d55b7
5 changed files with 109 additions and 10 deletions
+7 -1
View File
@@ -418,7 +418,11 @@ impl PathCategory {
PathCategory::AdminApi
} else if path.starts_with("/rustfs/console") {
PathCategory::Console
} else if path == "/health" || path.starts_with("/health/") {
} else if path == "/health"
|| path.starts_with("/health/")
|| path == "/minio/health/live"
|| path == "/minio/health/ready"
{
PathCategory::Probe
} else {
PathCategory::S3DataPlane
@@ -766,6 +770,8 @@ mod tests {
assert_eq!(PathCategory::classify("/health"), PathCategory::Probe);
assert_eq!(PathCategory::classify("/health/live"), PathCategory::Probe);
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);
}
#[test]
+91 -6
View File
@@ -20,8 +20,8 @@ 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, 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_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::{
@@ -883,8 +883,8 @@ fn resolve_public_health_probe(method: &Method, path: &str) -> Option<HealthProb
}
match path {
HEALTH_PREFIX | HEALTH_COMPAT_LIVE_PATH => Some(HealthProbe::Liveness),
HEALTH_READY_PATH => Some(HealthProbe::Readiness),
HEALTH_PREFIX | HEALTH_COMPAT_LIVE_PATH | MINIO_HEALTH_LIVE_PATH => Some(HealthProbe::Liveness),
HEALTH_READY_PATH | MINIO_HEALTH_READY_PATH => Some(HealthProbe::Readiness),
_ => None,
}
}
@@ -1279,8 +1279,15 @@ impl ConditionalCorsLayer {
}
/// Exact paths that should be excluded from being treated as S3 paths.
const EXCLUDED_EXACT_PATHS: &'static [&'static str] =
&["/health", "/health/live", "/health/ready", "/profile/cpu", "/profile/memory"];
const EXCLUDED_EXACT_PATHS: &'static [&'static str] = &[
"/health",
"/health/live",
"/health/ready",
"/minio/health/live",
"/minio/health/ready",
"/profile/cpu",
"/profile/memory",
];
fn is_s3_path(path: &str) -> bool {
// Exclude Admin, Console, RPC, and configured special paths
@@ -1854,6 +1861,59 @@ mod tests {
.await;
}
#[tokio::test]
#[serial]
async fn public_health_endpoint_layer_handles_minio_health_live_path() {
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_LIVE_PATH)
.body(Full::<Bytes>::from(Bytes::new()))
.expect("request"),
)
.await
.expect("health response");
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(calls.load(Ordering::SeqCst), 0);
})
.await;
}
#[tokio::test]
#[serial]
async fn public_health_endpoint_layer_handles_minio_health_ready_head_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::HEAD)
.uri(MINIO_HEALTH_READY_PATH)
.body(Full::<Bytes>::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);
let body = BodyExt::collect(response.into_body()).await.expect("body").to_bytes();
assert!(body.is_empty());
})
.await;
}
#[tokio::test]
#[serial]
async fn public_health_endpoint_layer_forwards_unknown_health_path_when_endpoint_disabled() {
@@ -1879,6 +1939,31 @@ mod tests {
.await;
}
#[tokio::test]
#[serial]
async fn public_health_endpoint_layer_forwards_minio_health_alias_when_endpoint_disabled() {
async_with_vars([(rustfs_config::ENV_HEALTH_ENDPOINT_ENABLE, Some("false"))], 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_LIVE_PATH)
.body(Full::<Bytes>::from(Bytes::new()))
.expect("request"),
)
.await
.expect("inner response");
assert_eq!(response.status(), StatusCode::IM_A_TEAPOT);
assert_eq!(calls.load(Ordering::SeqCst), 1);
})
.await;
}
#[test]
fn alias_busy_threshold_exceeded_requires_switch_and_positive_threshold() {
with_var(rustfs_config::ENV_HEALTH_COMPAT_BUSY_CHECK_ENABLE, Some("true"), || {
+3 -3
View File
@@ -52,9 +52,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, 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_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;
+6
View File
@@ -34,6 +34,12 @@ pub(crate) const HEALTH_READY_PATH: &str = "/health/ready";
/// Health liveness probe compatibility alias path.
pub(crate) const HEALTH_COMPAT_LIVE_PATH: &str = "/health/live";
/// MinIO-compatible health liveness probe alias path.
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";
/// Predefined administrative prefix for RustFS server routes.
/// This prefix is used for endpoints that handle administrative tasks
/// such as configuration, monitoring, and management.
+2
View File
@@ -136,6 +136,8 @@ fn is_probe_path(path: &str) -> bool {
| crate::server::HEALTH_PREFIX
| crate::server::HEALTH_COMPAT_LIVE_PATH
| crate::server::HEALTH_READY_PATH
| crate::server::MINIO_HEALTH_LIVE_PATH
| crate::server::MINIO_HEALTH_READY_PATH
| crate::server::FAVICON_PATH
);