Gate 206 response checksum headers on full-range coverage

This commit is contained in:
2026-04-24 20:18:41 +08:00
parent 5aba9ac9e9
commit 37541ffba1
4 changed files with 103 additions and 8 deletions

View File

@@ -2783,7 +2783,9 @@ async fn stream_partial_content(
headers.insert("x-amz-server-side-encryption", alg.parse().unwrap());
}
apply_stored_response_headers(&mut headers, &meta.internal_metadata);
apply_stored_checksum_headers(&mut headers, &meta.internal_metadata);
if start == 0 && end + 1 == plaintext_size {
apply_stored_checksum_headers(&mut headers, &meta.internal_metadata);
}
if let Some(ref requested_version) = query.version_id {
if let Ok(value) = requested_version.parse() {
headers.insert("x-amz-version-id", value);

View File

@@ -1905,6 +1905,99 @@ async fn test_range_request() {
assert_eq!(&body[..], b"data.");
}
#[tokio::test]
async fn test_range_get_omits_whole_object_checksum() {
use base64::engine::general_purpose::STANDARD as B64;
use sha2::{Digest, Sha256};
let (app, _tmp) = test_app();
app.clone()
.oneshot(signed_request(Method::PUT, "/csum-bucket", Body::empty()))
.await
.unwrap();
let data = b"Hello, World! This is range checksum data.";
let sha = B64.encode(Sha256::digest(data));
app.clone()
.oneshot(
Request::builder()
.method(Method::PUT)
.uri("/csum-bucket/obj.bin")
.header("x-access-key", TEST_ACCESS_KEY)
.header("x-secret-key", TEST_SECRET_KEY)
.header("x-amz-checksum-sha256", &sha)
.body(Body::from(&data[..]))
.unwrap(),
)
.await
.unwrap();
let full = app
.clone()
.oneshot(
Request::builder()
.uri("/csum-bucket/obj.bin")
.header("x-access-key", TEST_ACCESS_KEY)
.header("x-secret-key", TEST_SECRET_KEY)
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(full.status(), StatusCode::OK);
assert_eq!(
full.headers().get("x-amz-checksum-sha256").unwrap(),
sha.as_str()
);
let partial = app
.clone()
.oneshot(
Request::builder()
.uri("/csum-bucket/obj.bin")
.header("x-access-key", TEST_ACCESS_KEY)
.header("x-secret-key", TEST_SECRET_KEY)
.header("range", "bytes=0-4")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(partial.status(), StatusCode::PARTIAL_CONTENT);
for algo in ["sha256", "sha1", "crc32", "crc32c", "crc64nvme"] {
let header = format!("x-amz-checksum-{}", algo);
assert!(
partial.headers().get(&header).is_none(),
"ranged GET must not include {}",
header
);
}
let body_bytes = partial.into_body().collect().await.unwrap().to_bytes();
assert_eq!(&body_bytes[..], &data[..5]);
let full_range = format!("bytes=0-{}", data.len() - 1);
let covering = app
.oneshot(
Request::builder()
.uri("/csum-bucket/obj.bin")
.header("x-access-key", TEST_ACCESS_KEY)
.header("x-secret-key", TEST_SECRET_KEY)
.header("range", &full_range)
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(covering.status(), StatusCode::PARTIAL_CONTENT);
assert_eq!(
covering.headers().get("x-amz-checksum-sha256").unwrap(),
sha.as_str()
);
}
#[tokio::test]
async fn test_copy_object() {
let (app, _tmp) = test_app();