From 58a317113933d3ff07f2112325de32adc9ed1bf7 Mon Sep 17 00:00:00 2001 From: Matthew Turner Date: Sat, 2 Aug 2025 07:48:39 -0400 Subject: [PATCH 1/4] Add storage class for aws and gcp --- src/attributes.rs | 4 ++++ src/aws/client.rs | 2 ++ src/gcp/client.rs | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/attributes.rs b/src/attributes.rs index 11cf27c8..f218fd2e 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -45,6 +45,10 @@ pub enum Attribute { /// /// See [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) CacheControl, + /// Specifies the storage class of the object. + /// + /// See [AWS](https://aws.amazon.com/s3/storage-classes/) and [GCP](https://cloud.google.com/storage/docs/storage-classes). + StorageClass, /// Specifies a user-defined metadata field for the object /// /// The String is a user-defined key diff --git a/src/aws/client.rs b/src/aws/client.rs index a99db159..913859dd 100644 --- a/src/aws/client.rs +++ b/src/aws/client.rs @@ -61,6 +61,7 @@ const VERSION_HEADER: &str = "x-amz-version-id"; const SHA256_CHECKSUM: &str = "x-amz-checksum-sha256"; const USER_DEFINED_METADATA_HEADER_PREFIX: &str = "x-amz-meta-"; const ALGORITHM: &str = "x-amz-checksum-algorithm"; +const STORAGE_CLASS: &str = "x-amz-storage-class"; /// A specialized `Error` for object store-related errors #[derive(Debug, thiserror::Error)] @@ -373,6 +374,7 @@ impl Request<'_> { has_content_type = true; builder.header(CONTENT_TYPE, v.as_ref()) } + Attribute::StorageClass => builder.header(STORAGE_CLASS, v.as_ref()), Attribute::Metadata(k_suffix) => builder.header( &format!("{USER_DEFINED_METADATA_HEADER_PREFIX}{k_suffix}"), v.as_ref(), diff --git a/src/gcp/client.rs b/src/gcp/client.rs index a988cc45..47af709d 100644 --- a/src/gcp/client.rs +++ b/src/gcp/client.rs @@ -51,6 +51,7 @@ use std::sync::Arc; const VERSION_HEADER: &str = "x-goog-generation"; const DEFAULT_CONTENT_TYPE: &str = "application/octet-stream"; const USER_DEFINED_METADATA_HEADER_PREFIX: &str = "x-goog-meta-"; +const STORAGE_CLASS: &str = "x-goog-storage-class"; static VERSION_MATCH: HeaderName = HeaderName::from_static("x-goog-if-generation-match"); @@ -201,6 +202,7 @@ impl Request<'_> { has_content_type = true; builder.header(CONTENT_TYPE, v.as_ref()) } + Attribute::StorageClass => builder.header(STORAGE_CLASS, v.as_ref()), Attribute::Metadata(k_suffix) => builder.header( &format!("{USER_DEFINED_METADATA_HEADER_PREFIX}{k_suffix}"), v.as_ref(), From 4108bef96b7835ddb72d34ea742aeeb5a82454b2 Mon Sep 17 00:00:00 2001 From: Matthew Turner Date: Thu, 4 Sep 2025 09:14:44 -0400 Subject: [PATCH 2/4] Add azure storage class attribute --- src/azure/client.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/azure/client.rs b/src/azure/client.rs index c7440a07..1e96aac0 100644 --- a/src/azure/client.rs +++ b/src/azure/client.rs @@ -48,6 +48,7 @@ use std::time::Duration; use url::Url; const VERSION_HEADER: &str = "x-ms-version-id"; +const ACCESS_TIER_HEADER: &str = "x-ms-access-tier"; const USER_DEFINED_METADATA_HEADER_PREFIX: &str = "x-ms-meta-"; static MS_CACHE_CONTROL: HeaderName = HeaderName::from_static("x-ms-blob-cache-control"); static MS_CONTENT_TYPE: HeaderName = HeaderName::from_static("x-ms-blob-content-type"); @@ -242,6 +243,7 @@ impl PutRequest<'_> { has_content_type = true; builder.header(&MS_CONTENT_TYPE, v.as_ref()) } + Attribute::StorageClass => builder.header(ACCESS_TIER_HEADER, v.as_ref()), Attribute::Metadata(k_suffix) => builder.header( &format!("{USER_DEFINED_METADATA_HEADER_PREFIX}{k_suffix}"), v.as_ref(), From be6fe1fc58116128a684227e66aaacbdff96f286 Mon Sep 17 00:00:00 2001 From: Matthew Turner Date: Thu, 4 Sep 2025 09:21:48 -0400 Subject: [PATCH 3/4] Update attribute docs --- src/attributes.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/attributes.rs b/src/attributes.rs index f218fd2e..cac5b36b 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -47,7 +47,11 @@ pub enum Attribute { CacheControl, /// Specifies the storage class of the object. /// - /// See [AWS](https://aws.amazon.com/s3/storage-classes/) and [GCP](https://cloud.google.com/storage/docs/storage-classes). + /// See [AWS](https://aws.amazon.com/s3/storage-classes/), + /// [GCP](https://cloud.google.com/storage/docs/storage-classes), and + /// [Azure](https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier). + /// `StorageClass` is used as the name for this attribute because 2 of the 3 storage providers + /// use that name StorageClass, /// Specifies a user-defined metadata field for the object /// From 9ca999c4f8869d180deb9eca7e844f9ee9d3a9d9 Mon Sep 17 00:00:00 2001 From: Matthew Turner Date: Thu, 4 Sep 2025 09:35:54 -0400 Subject: [PATCH 4/4] Update http client --- src/http/client.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/http/client.rs b/src/http/client.rs index 272f7c60..d08e9faf 100644 --- a/src/http/client.rs +++ b/src/http/client.rs @@ -196,6 +196,10 @@ impl Client { has_content_type = true; builder.header(CONTENT_TYPE, v.as_ref()) } + Attribute::StorageClass => { + tracing::warn!("StorageClass attribute not supported on HTTP client as header key is unknown"); + builder + } // Ignore metadata attributes Attribute::Metadata(_) => builder, };