From 2f5e4a8de4dd7e82f10ab7f68a52a99a1d816a49 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Wed, 1 Jul 2026 23:16:52 +0800 Subject: [PATCH] fix: auto-repair breaking changes from a2ec13ab0 (#4148) --- crates/e2e_test/src/admin_timeout_regression_test.rs | 9 ++++++++- rustfs/src/app/object_usecase.rs | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/e2e_test/src/admin_timeout_regression_test.rs b/crates/e2e_test/src/admin_timeout_regression_test.rs index 9fb10acae..c561e5d76 100644 --- a/crates/e2e_test/src/admin_timeout_regression_test.rs +++ b/crates/e2e_test/src/admin_timeout_regression_test.rs @@ -20,6 +20,7 @@ use rustfs_madmin::{ITEM_OFFLINE, InfoMessage, StorageInfo}; use rustfs_signer::constants::UNSIGNED_PAYLOAD; use rustfs_signer::sign_v4; use s3s::Body; +use serde::Deserialize; use serial_test::serial; use std::error::Error; use std::process::Command; @@ -28,6 +29,11 @@ use uuid::Uuid; const BUCKET: &str = "issue-2525-admin-timeout"; +#[derive(Deserialize)] +struct StorageInfoResponse { + info: StorageInfo, +} + async fn signed_admin_get( url: &str, access_key: &str, @@ -60,7 +66,8 @@ async fn fetch_info(cluster: &RustFSTestClusterEnvironment) -> Result Result> { let url = format!("{}/rustfs/admin/v3/storageinfo", cluster.nodes[0].url); let response = signed_admin_get(&url, &cluster.access_key, &cluster.secret_key).await?; - parse_json_response(response, "storage info").await + let wrapper: StorageInfoResponse = parse_json_response(response, "storage info").await?; + Ok(wrapper.info) } async fn parse_json_response( diff --git a/rustfs/src/app/object_usecase.rs b/rustfs/src/app/object_usecase.rs index 1262d3f3d..cb74abad7 100644 --- a/rustfs/src/app/object_usecase.rs +++ b/rustfs/src/app/object_usecase.rs @@ -72,6 +72,7 @@ use super::storage_api::object_usecase::object_utils::to_s3s_etag; use super::storage_api::object_usecase::options::{ copy_dst_opts, copy_src_opts, del_opts, extract_metadata, extract_metadata_from_mime_with_object_name, filter_object_metadata, get_content_sha256_with_query, get_opts, normalize_content_encoding_for_storage, put_opts, + validate_archive_content_encoding, }; use super::storage_api::object_usecase::request_context::{self, spawn_traced}; use super::storage_api::object_usecase::s3_api::multipart::parse_list_parts_params; @@ -2815,6 +2816,13 @@ impl DefaultObjectUsecase { validate_object_key(&key, request_method_name)?; validate_table_catalog_object_mutation(&bucket, &key).await?; + // Validate archive content encoding (reject when strict mode is enabled) + validate_archive_content_encoding( + &key, + req.headers.get("content-type").and_then(|value| value.to_str().ok()), + req.headers.get("content-encoding").and_then(|value| value.to_str().ok()), + )?; + if let Some(size) = content_length { self.check_bucket_quota(&bucket, quota_operation, size as u64).await?; }