mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-24 13:16:28 +00:00
fix(s3): return content disposition on get object (#3504)
This commit is contained in:
@@ -2326,6 +2326,7 @@ impl DefaultObjectUsecase {
|
|||||||
// x-amz-expiration: predict from lifecycle configuration
|
// x-amz-expiration: predict from lifecycle configuration
|
||||||
let expiration = resolve_put_object_expiration(bucket, &info).await;
|
let expiration = resolve_put_object_expiration(bucket, &info).await;
|
||||||
let storage_class = response_storage_class(&info, &info.user_defined);
|
let storage_class = response_storage_class(&info, &info.user_defined);
|
||||||
|
let content_disposition = info.user_defined.get("content-disposition").cloned();
|
||||||
|
|
||||||
let output = GetObjectOutput {
|
let output = GetObjectOutput {
|
||||||
body,
|
body,
|
||||||
@@ -2333,6 +2334,7 @@ impl DefaultObjectUsecase {
|
|||||||
last_modified,
|
last_modified,
|
||||||
content_type,
|
content_type,
|
||||||
content_encoding: info.content_encoding.clone(),
|
content_encoding: info.content_encoding.clone(),
|
||||||
|
content_disposition,
|
||||||
accept_ranges: Some(ACCEPT_RANGES_BYTES.to_string()),
|
accept_ranges: Some(ACCEPT_RANGES_BYTES.to_string()),
|
||||||
content_range,
|
content_range,
|
||||||
e_tag: info.etag.map(|etag| to_s3s_etag(&etag)),
|
e_tag: info.etag.map(|etag| to_s3s_etag(&etag)),
|
||||||
@@ -5296,6 +5298,66 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn build_get_object_output_context_returns_content_disposition() {
|
||||||
|
let mut metadata = HashMap::new();
|
||||||
|
metadata.insert("content-disposition".to_string(), "attachment; filename=\"demo.png\"".to_string());
|
||||||
|
|
||||||
|
let info = ObjectInfo {
|
||||||
|
bucket: "test-bucket".to_string(),
|
||||||
|
name: "path/raw".to_string(),
|
||||||
|
user_defined: Arc::new(metadata),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let input = GetObjectInput::builder()
|
||||||
|
.bucket("test-bucket".to_string())
|
||||||
|
.key("path/raw".to_string())
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
let req = build_request(input, Method::GET);
|
||||||
|
let usecase = DefaultObjectUsecase::without_context();
|
||||||
|
let queue_status = concurrency::IoQueueStatus::default();
|
||||||
|
|
||||||
|
let context = usecase
|
||||||
|
.build_get_object_output_context(
|
||||||
|
&req,
|
||||||
|
get_concurrency_manager(),
|
||||||
|
"test-bucket",
|
||||||
|
"path/raw",
|
||||||
|
info.clone(),
|
||||||
|
info,
|
||||||
|
wrap_reader(tokio::io::empty()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
Duration::ZERO,
|
||||||
|
0.0,
|
||||||
|
&queue_status,
|
||||||
|
1,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("get object output context");
|
||||||
|
|
||||||
|
assert_eq!(context.output.content_disposition.as_deref(), Some("attachment; filename=\"demo.png\""));
|
||||||
|
assert!(
|
||||||
|
!context
|
||||||
|
.output
|
||||||
|
.metadata
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|metadata| metadata.contains_key("content-disposition"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn execute_get_object_rejects_zero_part_number() {
|
async fn execute_get_object_rejects_zero_part_number() {
|
||||||
let input = GetObjectInput::builder()
|
let input = GetObjectInput::builder()
|
||||||
|
|||||||
Reference in New Issue
Block a user