You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2025/09/11 08:58:05 UTC

(opendal) branch main updated: feat(services/oss): allow users to specify endpoint addressing style (#6504)

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 0e5fa5e2b feat(services/oss): allow users to specify endpoint addressing style (#6504)
0e5fa5e2b is described below

commit 0e5fa5e2b6419c2238de4bf689359253e4989b86
Author: Howard Lau <ho...@hotmail.com>
AuthorDate: Thu Sep 11 16:58:00 2025 +0800

    feat(services/oss): allow users to specify endpoint addressing style (#6504)
---
 core/src/services/oss/backend.rs | 95 +++++++++++++++++++++++++++++++++++++---
 core/src/services/oss/config.rs  |  4 ++
 core/src/services/oss/docs.md    |  2 +
 3 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs
index cfcdcb2a3..6cf1a725b 100644
--- a/core/src/services/oss/backend.rs
+++ b/core/src/services/oss/backend.rs
@@ -104,6 +104,21 @@ impl OssBuilder {
         self
     }
 
+    /// Set addressing style for the endpoint.
+    ///
+    /// Available values: `virtual`, `cname`, `path`.
+    ///
+    /// - `virtual`: Use virtual addressing style, i.e. `http://bucket.oss-<region>.aliyuncs.com/object`
+    /// - `cname`: Use cname addressing style, i.e. `http://mydomain.com/object` with mydomain.com bound to your bucket.
+    /// - `path`: Use path addressing style. i.e. `http://oss-<region>.aliyuncs.com/bucket/object`
+    ///
+    /// - If not set, default value is `virtual`.
+    pub fn addressing_style(mut self, addressing_style: &str) -> Self {
+        self.config.addressing_style = Some(addressing_style.to_string());
+
+        self
+    }
+
     /// Set bucket versioning status for this backend
     pub fn enable_versioning(mut self, enabled: bool) -> Self {
         self.config.enable_versioning = enabled;
@@ -128,6 +143,19 @@ impl OssBuilder {
         self
     }
 
+    /// Set addressing style for presign endpoint.
+    ///
+    /// Similar to setting addressing style for endpoint.
+    ///
+    /// - If both presign_endpoint and presign_addressing_style are not set, they are the same as endpoint's configurations.
+    ///
+    /// - If presign_endpoint is set, but presign_addressing_style is not set, default value is `virtual`.
+    pub fn presign_addressing_style(mut self, addressing_style: &str) -> Self {
+        self.config.presign_addressing_style = Some(addressing_style.to_string());
+
+        self
+    }
+
     /// Set access_key_id of this backend.
     ///
     /// - If access_key_id is set, we will take user's input first.
@@ -178,7 +206,12 @@ impl OssBuilder {
     }
 
     /// preprocess the endpoint option
-    fn parse_endpoint(&self, endpoint: &Option<String>, bucket: &str) -> Result<(String, String)> {
+    fn parse_endpoint(
+        &self,
+        endpoint: &Option<String>,
+        bucket: &str,
+        addressing_style: AddressingStyle,
+    ) -> Result<(String, String)> {
         let (endpoint, host) = match endpoint.clone() {
             Some(ep) => {
                 let uri = ep.parse::<Uri>().map_err(|err| {
@@ -192,7 +225,23 @@ impl OssBuilder {
                         .with_context("service", Scheme::Oss)
                         .with_context("endpoint", &ep)
                 })?;
-                let full_host = if let Some(port) = uri.port_u16() {
+                let full_host = match addressing_style {
+                    AddressingStyle::Virtual => {
+                        if let Some(port) = uri.port_u16() {
+                            format!("{bucket}.{host}:{port}")
+                        } else {
+                            format!("{bucket}.{host}")
+                        }
+                    }
+                    AddressingStyle::Cname | AddressingStyle::Path => {
+                        if let Some(port) = uri.port_u16() {
+                            format!("{host}:{port}")
+                        } else {
+                            host.to_string()
+                        }
+                    }
+                };
+                if let Some(port) = uri.port_u16() {
                     format!("{bucket}.{host}:{port}")
                 } else {
                     format!("{bucket}.{host}")
@@ -210,6 +259,10 @@ impl OssBuilder {
                     },
                     None => format!("https://{full_host}"),
                 };
+                let endpoint = match addressing_style {
+                    AddressingStyle::Path => format!("{}/{}", endpoint, bucket),
+                    AddressingStyle::Cname | AddressingStyle::Virtual => endpoint,
+                };
                 (endpoint, full_host)
             }
             None => {
@@ -329,6 +382,30 @@ impl OssBuilder {
     }
 }
 
+enum AddressingStyle {
+    Path,
+    Cname,
+    Virtual,
+}
+
+impl TryFrom<&Option<String>> for AddressingStyle {
+    type Error = Error;
+
+    fn try_from(value: &Option<String>) -> Result<Self> {
+        match value.as_deref() {
+            None | Some("virtual") => Ok(AddressingStyle::Virtual),
+            Some("path") => Ok(AddressingStyle::Path),
+            Some("cname") => Ok(AddressingStyle::Cname),
+            Some(v) => Err(Error::new(
+                ErrorKind::ConfigInvalid,
+                "Invalid addressing style, available: `virtual`, `path`, `cname`",
+            )
+            .with_context("service", Scheme::Oss)
+            .with_context("addressing_style", v)),
+        }
+    }
+}
+
 impl Builder for OssBuilder {
     type Config = OssConfig;
 
@@ -349,12 +426,20 @@ impl Builder for OssBuilder {
 
         // Retrieve endpoint and host by parsing the endpoint option and bucket. If presign_endpoint is not
         // set, take endpoint as default presign_endpoint.
-        let (endpoint, host) = self.parse_endpoint(&self.config.endpoint, bucket)?;
+        let (endpoint, host) = self.parse_endpoint(
+            &self.config.endpoint,
+            bucket,
+            (&self.config.addressing_style).try_into()?,
+        )?;
         debug!("backend use bucket {}, endpoint: {}", &bucket, &endpoint);
 
         let presign_endpoint = if self.config.presign_endpoint.is_some() {
-            self.parse_endpoint(&self.config.presign_endpoint, bucket)?
-                .0
+            self.parse_endpoint(
+                &self.config.presign_endpoint,
+                bucket,
+                (&self.config.presign_addressing_style).try_into()?,
+            )?
+            .0
         } else {
             endpoint.clone()
         };
diff --git a/core/src/services/oss/config.rs b/core/src/services/oss/config.rs
index cdd6b8fbe..abbf94d03 100644
--- a/core/src/services/oss/config.rs
+++ b/core/src/services/oss/config.rs
@@ -35,6 +35,10 @@ pub struct OssConfig {
     pub presign_endpoint: Option<String>,
     /// Bucket for oss.
     pub bucket: String,
+    /// Addressing style for oss.
+    pub addressing_style: Option<String>,
+    /// Pre sign addressing style for oss.
+    pub presign_addressing_style: Option<String>,
 
     /// is bucket versioning enabled for this bucket
     pub enable_versioning: bool,
diff --git a/core/src/services/oss/docs.md b/core/src/services/oss/docs.md
index 3a69595e6..dcbac45a2 100644
--- a/core/src/services/oss/docs.md
+++ b/core/src/services/oss/docs.md
@@ -21,7 +21,9 @@ This service can be used to:
 - `root`: Set the work dir for backend.
 - `bucket`: Set the container name for backend.
 - `endpoint`: Set the endpoint for backend.
+- `addressing_style`: Set the addressing style for endpoint.
 - `presign_endpoint`: Set the endpoint for presign.
+- `presign_addressing_style`: Set the addressing style for presign endpoint.
 - `access_key_id`: Set the access_key_id for backend.
 - `access_key_secret`: Set the access_key_secret for backend.
 - `role_arn`: Set the role of backend.