fix(s3): advertise byte ranges on head object (#2802)

This commit is contained in:
安正超
2026-05-05 12:29:25 +08:00
committed by GitHub
parent 36b3d21c44
commit 3208f930c5
3 changed files with 59 additions and 1 deletions
@@ -0,0 +1,52 @@
use crate::common::{RustFSTestEnvironment, init_logging};
use aws_sdk_s3::primitives::ByteStream;
use serial_test::serial;
use tracing::info;
const RANGE_HEAD_BUCKET: &str = "range-head-test-bucket";
const RANGE_HEAD_KEY: &str = "range-head-object.bin";
const ACCEPT_RANGES_BYTES: &str = "bytes";
#[tokio::test]
#[serial]
async fn head_object_advertises_accept_ranges() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
init_logging();
info!("Starting HeadObject Accept-Ranges regression test");
let mut env = RustFSTestEnvironment::new().await?;
env.start_rustfs_server(Vec::new()).await?;
let client = env.create_s3_client();
env.create_test_bucket(RANGE_HEAD_BUCKET).await?;
client
.put_object()
.bucket(RANGE_HEAD_BUCKET)
.key(RANGE_HEAD_KEY)
.body(ByteStream::from_static(b"0123456789abcdef"))
.send()
.await?;
let head = client
.head_object()
.bucket(RANGE_HEAD_BUCKET)
.key(RANGE_HEAD_KEY)
.send()
.await?;
assert_eq!(
head.accept_ranges(),
Some(ACCEPT_RANGES_BYTES),
"HeadObject should advertise byte range support"
);
client
.delete_object()
.bucket(RANGE_HEAD_BUCKET)
.key(RANGE_HEAD_KEY)
.send()
.await?;
env.delete_test_bucket(RANGE_HEAD_BUCKET).await?;
env.stop_server();
Ok(())
}
+3
View File
@@ -104,6 +104,9 @@ mod checksum_upload_test;
#[cfg(test)]
mod group_delete_test;
#[cfg(test)]
mod head_object_range_test;
// S3 dummy-compat bucket API tests
#[cfg(test)]
mod bucket_logging_test;
+4 -1
View File
@@ -131,6 +131,8 @@ use tokio_util::io::{ReaderStream, StreamReader};
use tracing::{debug, error, info, instrument, warn};
use uuid::Uuid;
const ACCEPT_RANGES_BYTES: &str = "bytes";
struct DeadlockRequestGuard {
deadlock_detector: Arc<deadlock_detector::DeadlockDetector>,
request_id: String,
@@ -2117,7 +2119,7 @@ impl DefaultObjectUsecase {
last_modified,
content_type,
content_encoding: info.content_encoding.clone(),
accept_ranges: Some("bytes".to_string()),
accept_ranges: Some(ACCEPT_RANGES_BYTES.to_string()),
content_range,
e_tag: info.etag.map(|etag| to_s3s_etag(&etag)),
metadata: filter_object_metadata(&info.user_defined),
@@ -3625,6 +3627,7 @@ impl DefaultObjectUsecase {
cache_control,
content_disposition,
content_language,
accept_ranges: Some(ACCEPT_RANGES_BYTES.to_string()),
website_redirect_location,
expires,
last_modified,