From 5d74f592e5c49b8afff7c20a9459993b61ada7fc Mon Sep 17 00:00:00 2001 From: haoqixu Date: Thu, 22 Aug 2024 02:12:04 +0800 Subject: [PATCH] feat(services-s3): support user defined metadata --- core/src/services/s3/backend.rs | 18 ++++++++++++++++++ core/src/services/s3/core.rs | 11 ++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/core/src/services/s3/backend.rs b/core/src/services/s3/backend.rs index 5e8fd0a5436..f124f0cea34 100644 --- a/core/src/services/s3/backend.rs +++ b/core/src/services/s3/backend.rs @@ -1071,6 +1071,8 @@ impl Access for S3Backend { write_can_multi: true, write_with_cache_control: true, write_with_content_type: true, + write_with_user_metadata: true, + // The min multipart size of S3 is 5 MiB. // // ref: @@ -1116,6 +1118,22 @@ impl Access for S3Backend { let headers = resp.headers(); let mut meta = parse_into_metadata(path, headers)?; + let user_meta: HashMap = headers + .iter() + .filter_map(|(name, _)| { + name.as_str() + .strip_prefix(constants::X_AMZ_META_PREFIX) + .and_then(|stripped_key| { + parse_header_to_str(headers, name) + .unwrap_or(None) + .map(|val| (stripped_key.to_string(), val.to_string())) + }) + }) + .collect(); + if !user_meta.is_empty() { + meta.with_user_metadata(user_meta); + } + if let Some(v) = parse_header_to_str(headers, "x-amz-version-id")? { meta.set_version(v); } diff --git a/core/src/services/s3/core.rs b/core/src/services/s3/core.rs index baf11789fdf..d11d5f3908c 100644 --- a/core/src/services/s3/core.rs +++ b/core/src/services/s3/core.rs @@ -47,7 +47,7 @@ use serde::Serialize; use crate::raw::*; use crate::*; -mod constants { +pub mod constants { pub const X_AMZ_COPY_SOURCE: &str = "x-amz-copy-source"; pub const X_AMZ_SERVER_SIDE_ENCRYPTION: &str = "x-amz-server-side-encryption"; @@ -68,6 +68,8 @@ mod constants { pub const X_AMZ_COPY_SOURCE_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5: &str = "x-amz-copy-source-server-side-encryption-customer-key-md5"; + pub const X_AMZ_META_PREFIX: &str = "x-amz-meta-"; + pub const RESPONSE_CONTENT_DISPOSITION: &str = "response-content-disposition"; pub const RESPONSE_CONTENT_TYPE: &str = "response-content-type"; pub const RESPONSE_CACHE_CONTROL: &str = "response-cache-control"; @@ -456,6 +458,13 @@ impl S3Core { req = req.header(HeaderName::from_static(constants::X_AMZ_STORAGE_CLASS), v); } + // Set user metadata headers. + if let Some(user_metadata) = args.user_metadata() { + for (key, value) in user_metadata { + req = req.header(format!("{}{}", constants::X_AMZ_META_PREFIX, key), value) + } + } + // Set SSE headers. req = self.insert_sse_headers(req, true);