From 2edf0ed74783d3280a696e327195251c0434d241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=AD=A3=E8=B6=85?= Date: Thu, 12 Feb 2026 10:46:07 +0800 Subject: [PATCH] refactor(admin): extract health check handler module (#1777) --- rustfs/src/admin/handlers.rs | 47 +-------------------- rustfs/src/admin/handlers/health.rs | 65 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 45 deletions(-) create mode 100644 rustfs/src/admin/handlers/health.rs diff --git a/rustfs/src/admin/handlers.rs b/rustfs/src/admin/handlers.rs index cc4d5ed46..c48a820a0 100644 --- a/rustfs/src/admin/handlers.rs +++ b/rustfs/src/admin/handlers.rs @@ -75,6 +75,7 @@ use url::Host; pub mod bucket_meta; pub mod event; pub mod group; +pub mod health; pub mod kms; pub mod kms_dynamic; pub mod kms_keys; @@ -88,6 +89,7 @@ pub mod sts; pub mod tier; pub mod trace; pub mod user; +pub use health::HealthCheckHandler; #[derive(Debug, Serialize)] pub struct IsAdminResponse { @@ -105,51 +107,6 @@ pub struct AccountInfo { pub policy: BucketPolicy, } -/// Health check handler for endpoint monitoring -pub struct HealthCheckHandler {} - -#[async_trait::async_trait] -impl Operation for HealthCheckHandler { - async fn call(&self, req: S3Request, _params: Params<'_, '_>) -> S3Result> { - use serde_json::json; - - // Extract the original HTTP Method (encapsulated by s3s into S3Request) - let method = req.method; - - // Only GET and HEAD are allowed - if method != http::Method::GET && method != http::Method::HEAD { - // 405 Method Not Allowed - let mut headers = HeaderMap::new(); - headers.insert(http::header::ALLOW, HeaderValue::from_static("GET, HEAD")); - return Ok(S3Response::with_headers( - (StatusCode::METHOD_NOT_ALLOWED, Body::from("Method Not Allowed".to_string())), - headers, - )); - } - - let health_info = json!({ - "status": "ok", - "service": "rustfs-endpoint", - "timestamp": jiff::Zoned::now().to_string(), - "version": env!("CARGO_PKG_VERSION") - }); - - let mut headers = HeaderMap::new(); - headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); - - if method == http::Method::HEAD { - // HEAD: only returns the header and status code, not the body - return Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), headers)); - } - - // GET: Return JSON body normally - let body_str = serde_json::to_string(&health_info).unwrap_or_else(|_| "{}".to_string()); - let body = Body::from(body_str); - - Ok(S3Response::with_headers((StatusCode::OK, body), headers)) - } -} - pub struct IsAdminHandler {} #[async_trait::async_trait] impl Operation for IsAdminHandler { diff --git a/rustfs/src/admin/handlers/health.rs b/rustfs/src/admin/handlers/health.rs new file mode 100644 index 000000000..ff78e8831 --- /dev/null +++ b/rustfs/src/admin/handlers/health.rs @@ -0,0 +1,65 @@ +// Copyright 2024 RustFS Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::admin::router::Operation; +use http::{HeaderMap, HeaderValue}; +use hyper::StatusCode; +use matchit::Params; +use s3s::header::CONTENT_TYPE; +use s3s::{Body, S3Request, S3Response, S3Result}; + +/// Health check handler for endpoint monitoring +pub struct HealthCheckHandler {} + +#[async_trait::async_trait] +impl Operation for HealthCheckHandler { + async fn call(&self, req: S3Request, _params: Params<'_, '_>) -> S3Result> { + use serde_json::json; + + // Extract the original HTTP Method (encapsulated by s3s into S3Request) + let method = req.method; + + // Only GET and HEAD are allowed + if method != http::Method::GET && method != http::Method::HEAD { + // 405 Method Not Allowed + let mut headers = HeaderMap::new(); + headers.insert(http::header::ALLOW, HeaderValue::from_static("GET, HEAD")); + return Ok(S3Response::with_headers( + (StatusCode::METHOD_NOT_ALLOWED, Body::from("Method Not Allowed".to_string())), + headers, + )); + } + + let health_info = json!({ + "status": "ok", + "service": "rustfs-endpoint", + "timestamp": jiff::Zoned::now().to_string(), + "version": env!("CARGO_PKG_VERSION") + }); + + let mut headers = HeaderMap::new(); + headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); + + if method == http::Method::HEAD { + // HEAD: only returns the header and status code, not the body + return Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), headers)); + } + + // GET: Return JSON body normally + let body_str = serde_json::to_string(&health_info).unwrap_or_else(|_| "{}".to_string()); + let body = Body::from(body_str); + + Ok(S3Response::with_headers((StatusCode::OK, body), headers)) + } +}