This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 77e74d059 feat(services/s3): Add a way to specify a default object ACL
(#7186)
77e74d059 is described below
commit 77e74d05973b344a7c5fb67125124aee5d25b279
Author: Antoine D <[email protected]>
AuthorDate: Mon Mar 9 12:58:20 2026 +0100
feat(services/s3): Add a way to specify a default object ACL (#7186)
feat(services/s3): Add a way to specify a default ACL
This default ACL is used when creating an object.
https://github.com/apache/opendal/issues/5358
Note: I did not use a fixed list for the ACL but a String since I'm not an
expert on this, and I don't really know if, for all supported services, we can
restrict it the list of [canned
ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl).
---
core/services/s3/src/backend.rs | 7 +++++++
core/services/s3/src/config.rs | 4 ++++
core/services/s3/src/core.rs | 8 ++++++++
core/services/s3/src/docs.md | 31 +++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+)
diff --git a/core/services/s3/src/backend.rs b/core/services/s3/src/backend.rs
index d3ae6aa76..3c71d75e8 100644
--- a/core/services/s3/src/backend.rs
+++ b/core/services/s3/src/backend.rs
@@ -682,6 +682,12 @@ impl S3Builder {
None
}
+
+ /// Set default ACL for new objects.
+ pub fn default_acl(mut self, acl: &str) -> Self {
+ self.config.default_acl = Some(acl.to_string());
+ self
+ }
}
impl Builder for S3Builder {
@@ -960,6 +966,7 @@ impl Builder for S3Builder {
enable_request_payer: config.enable_request_payer,
signer,
checksum_algorithm,
+ default_acl: config.default_acl,
}),
})
}
diff --git a/core/services/s3/src/config.rs b/core/services/s3/src/config.rs
index 8e4a3c15d..8c219de6c 100644
--- a/core/services/s3/src/config.rs
+++ b/core/services/s3/src/config.rs
@@ -221,6 +221,10 @@ pub struct S3Config {
/// Indicates whether the client agrees to pay for the requests made to
the S3 bucket.
#[serde(alias = "aws_request_payer", alias = "request_payer")]
pub enable_request_payer: bool,
+
+ /// Default ACL for new objects.
+ /// Note that some s3 services like minio do not support this option.
+ pub default_acl: Option<String>,
}
impl Debug for S3Config {
diff --git a/core/services/s3/src/core.rs b/core/services/s3/src/core.rs
index 03e14483a..bdb1ec470 100644
--- a/core/services/s3/src/core.rs
+++ b/core/services/s3/src/core.rs
@@ -75,6 +75,8 @@ pub mod constants {
pub const X_AMZ_VERSION_ID: &str = "x-amz-version-id";
pub const X_AMZ_OBJECT_SIZE: &str = "x-amz-object-size";
+ pub const X_AMZ_ACL: &str = "x-amz-acl";
+
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";
@@ -97,6 +99,7 @@ pub struct S3Core {
pub allow_anonymous: bool,
pub disable_list_objects_v2: bool,
pub enable_request_payer: bool,
+ pub default_acl: Option<String>,
pub signer: Signer<Credential>,
pub checksum_algorithm: Option<ChecksumAlgorithm>,
@@ -330,6 +333,11 @@ impl S3Core {
req = req.header(format!("{X_AMZ_META_PREFIX}{key}"), value)
}
}
+
+ // Set ACL header.
+ if let Some(acl) = &self.default_acl {
+ req = req.header(constants::X_AMZ_ACL, acl);
+ }
req
}
diff --git a/core/services/s3/src/docs.md b/core/services/s3/src/docs.md
index 04cc80009..df279f35b 100644
--- a/core/services/s3/src/docs.md
+++ b/core/services/s3/src/docs.md
@@ -31,6 +31,7 @@ This service can be used to:
- `enable_virtual_host_style`: Enable virtual host style.
- `disable_write_with_if_match`: Disable write with if match.
- `enable_request_payer`: Enable the request payer for backend.
+- `default_acl`: Define the default access control list (ACL) when creating a
new object. Note that some s3 services like minio do not support this option.
Refer to [`S3Builder`]'s public API docs for more information.
@@ -237,3 +238,33 @@ async fn main() -> Result<()> {
Ok(())
}
```
+
+### S3 with default ACL
+
+```rust,no_run
+use log::info;
+use opendal_core::Operator;
+use opendal_core::Result;
+use opendal_service_s3::S3;
+
+#[tokio::main]
+async fn main() -> Result<()> {
+ let mut builder = S3::default()
+ // Setup builders
+ .root("/path/to/dir")
+ .bucket("test")
+ .region("us-east-1")
+ .endpoint("https://s3.amazonaws.com")
+ .access_key_id("access_key_id")
+ .secret_access_key("secret_access_key")
+ // Enable public-read ACL
+ .default_acl("public-read");
+
+ let op = Operator::new(builder)?.finish();
+ info!("operator: {:?}", op);
+
+ // New objects will be created with public-read ACL
+
+ Ok(())
+}
+```