fix(admin): normalize empty admin POST content length (#2843)

This commit is contained in:
cxymds
2026-05-07 10:52:21 +08:00
committed by GitHub
parent 5e0ca006f0
commit 06097a3c33
+57 -11
View File
@@ -259,19 +259,31 @@ where
} }
fn should_force_zero_content_length_for_admin_empty_body<B>(req: &HttpRequest<B>) -> bool { fn should_force_zero_content_length_for_admin_empty_body<B>(req: &HttpRequest<B>) -> bool {
req.method() == Method::PUT is_empty_body_admin_path(req.method(), req.uri().path()) && !req.headers().contains_key(http::header::CONTENT_LENGTH)
&& is_empty_body_admin_put_path(req.uri().path())
&& !req.headers().contains_key(http::header::CONTENT_LENGTH)
} }
fn is_empty_body_admin_put_path(path: &str) -> bool { fn is_empty_body_admin_path(method: &Method, path: &str) -> bool {
matches!( match *method {
path, Method::PUT => matches!(
"/minio/admin/v3/set-user-status" path,
| "/minio/admin/v3/set-group-status" "/minio/admin/v3/set-user-status"
| "/rustfs/admin/v3/set-user-status" | "/minio/admin/v3/set-group-status"
| "/rustfs/admin/v3/set-group-status" | "/rustfs/admin/v3/set-user-status"
) | "/rustfs/admin/v3/set-group-status"
),
Method::POST => matches!(
path,
"/minio/admin/v3/rebalance/start"
| "/minio/admin/v3/rebalance/stop"
| "/minio/admin/v3/pools/decommission"
| "/minio/admin/v3/pools/cancel"
| "/rustfs/admin/v3/rebalance/start"
| "/rustfs/admin/v3/rebalance/stop"
| "/rustfs/admin/v3/pools/decommission"
| "/rustfs/admin/v3/pools/cancel"
),
_ => false,
}
} }
#[derive(Clone)] #[derive(Clone)]
@@ -951,6 +963,29 @@ mod tests {
assert!(should_force_zero_content_length_for_admin_empty_body(&request)); assert!(should_force_zero_content_length_for_admin_empty_body(&request));
} }
#[test]
fn admin_empty_body_post_without_content_length_is_normalized() {
let paths = [
"/minio/admin/v3/rebalance/start",
"/minio/admin/v3/rebalance/stop",
"/minio/admin/v3/pools/decommission?pool=http%3A%2F%2Fminio-%7B1...4%7D%3A9000%2Fdata%7B1...2%7D",
"/minio/admin/v3/pools/cancel?pool=http%3A%2F%2Fminio-%7B1...4%7D%3A9000%2Fdata%7B1...2%7D",
"/rustfs/admin/v3/rebalance/start",
"/rustfs/admin/v3/rebalance/stop",
"/rustfs/admin/v3/pools/decommission?pool=http%3A%2F%2Fminio-%7B1...4%7D%3A9000%2Fdata%7B1...2%7D",
"/rustfs/admin/v3/pools/cancel?pool=http%3A%2F%2Fminio-%7B1...4%7D%3A9000%2Fdata%7B1...2%7D",
];
for path in paths {
let request = Request::builder().method(Method::POST).uri(path).body(()).expect("request");
assert!(
should_force_zero_content_length_for_admin_empty_body(&request),
"{path} should force Content-Length: 0"
);
}
}
#[test] #[test]
fn admin_request_with_explicit_content_length_is_left_unchanged() { fn admin_request_with_explicit_content_length_is_left_unchanged() {
let request = Request::builder() let request = Request::builder()
@@ -974,6 +1009,17 @@ mod tests {
assert!(!should_force_zero_content_length_for_admin_empty_body(&request)); assert!(!should_force_zero_content_length_for_admin_empty_body(&request));
} }
#[test]
fn non_empty_body_admin_post_path_is_not_normalized() {
let request = Request::builder()
.method(Method::POST)
.uri("/minio/admin/v3/update-service-account")
.body(())
.expect("request");
assert!(!should_force_zero_content_length_for_admin_empty_body(&request));
}
#[test] #[test]
fn test_strip_quotes_from_first_etag_removes_quotes() { fn test_strip_quotes_from_first_etag_removes_quotes() {
let input = String::from("<GetObjectAttributesOutput><ETag>\"abc\"</ETag></GetObjectAttributesOutput>"); let input = String::from("<GetObjectAttributesOutput><ETag>\"abc\"</ETag></GetObjectAttributesOutput>");