This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.0 by this push:
     new b358eafb4f3 branch-4.0: [fix](Azure)Fix Azure endpoint detection for 
sovereign clouds with force-global config support #60903 (#61006)
b358eafb4f3 is described below

commit b358eafb4f3bed913660bc2d98c41b067f864f05
Author: Calvin Kirs <[email protected]>
AuthorDate: Wed Mar 4 10:21:50 2026 +0800

    branch-4.0: [fix](Azure)Fix Azure endpoint detection for sovereign clouds 
with force-global config support #60903 (#61006)
    
    #60903
---
 be/src/common/config.cpp                           |  2 -
 be/src/common/config.h                             |  2 -
 be/src/io/fs/azure_obj_storage_client.cpp          |  3 -
 be/src/util/s3_util.cpp                            | 11 +--
 cloud/src/common/config.h                          |  2 -
 cloud/src/recycler/s3_accessor.cpp                 | 10 +--
 .../main/java/org/apache/doris/common/Config.java  | 26 ++++++--
 .../property/storage/AzureProperties.java          | 39 +++++++----
 .../property/storage/AzurePropertyUtils.java       | 63 +++++++++++++++--
 .../property/storage/AzurePropertiesTest.java      | 78 ++++++++++++++++++++++
 .../property/storage/AzurePropertyUtilsTest.java   | 46 ++++++++++++-
 11 files changed, 232 insertions(+), 50 deletions(-)

diff --git a/be/src/common/config.cpp b/be/src/common/config.cpp
index 840de574bec..c18c2e85225 100644
--- a/be/src/common/config.cpp
+++ b/be/src/common/config.cpp
@@ -1418,8 +1418,6 @@ DEFINE_Int64(wait_cancel_release_memory_ms, "5000");
 
 DEFINE_mBool(check_segment_when_build_rowset_meta, "false");
 
-DEFINE_mBool(force_azure_blob_global_endpoint, "false");
-
 DEFINE_mInt32(max_s3_client_retry, "10");
 DEFINE_mInt32(s3_read_base_wait_time_ms, "100");
 DEFINE_mInt32(s3_read_max_wait_time_ms, "800");
diff --git a/be/src/common/config.h b/be/src/common/config.h
index 61456c60dd6..a06317f6feb 100644
--- a/be/src/common/config.h
+++ b/be/src/common/config.h
@@ -1520,8 +1520,6 @@ DECLARE_mBool(check_segment_when_build_rowset_meta);
 
 DECLARE_Int32(num_query_ctx_map_partitions);
 
-DECLARE_mBool(force_azure_blob_global_endpoint);
-
 DECLARE_mBool(enable_s3_rate_limiter);
 DECLARE_mInt64(s3_get_bucket_tokens);
 DECLARE_mInt64(s3_get_token_per_second);
diff --git a/be/src/io/fs/azure_obj_storage_client.cpp 
b/be/src/io/fs/azure_obj_storage_client.cpp
index 026d5b56b93..7dd44db76d8 100644
--- a/be/src/io/fs/azure_obj_storage_client.cpp
+++ b/be/src/io/fs/azure_obj_storage_client.cpp
@@ -418,9 +418,6 @@ std::string 
AzureObjStorageClient::generate_presigned_url(const ObjectStoragePat
             Azure::Storage::StorageSharedKeyCredential(conf.ak, conf.sk));
 
     std::string endpoint = conf.endpoint;
-    if (doris::config::force_azure_blob_global_endpoint) {
-        endpoint = fmt::format("https://{}.blob.core.windows.net";, conf.ak);
-    }
     auto sasURL = fmt::format(SAS_TOKEN_URL_TEMPLATE, endpoint, conf.bucket, 
opts.key, sasToken);
     if (sasURL.find("://") == std::string::npos) {
         sasURL = "https://"; + sasURL;
diff --git a/be/src/util/s3_util.cpp b/be/src/util/s3_util.cpp
index 9f6f9ccdaf3..109fdd1710a 100644
--- a/be/src/util/s3_util.cpp
+++ b/be/src/util/s3_util.cpp
@@ -313,14 +313,9 @@ std::shared_ptr<io::ObjStorageClient> 
S3ClientFactory::_create_azure_client(
             
std::make_shared<Azure::Storage::StorageSharedKeyCredential>(s3_conf.ak, 
s3_conf.sk);
 
     const std::string container_name = s3_conf.bucket;
-    std::string uri;
-    if (config::force_azure_blob_global_endpoint) {
-        uri = fmt::format("https://{}.blob.core.windows.net/{}";, s3_conf.ak, 
container_name);
-    } else {
-        uri = fmt::format("{}/{}", s3_conf.endpoint, container_name);
-        if (s3_conf.endpoint.find("://") == std::string::npos) {
-            uri = "https://"; + uri;
-        }
+    std::string uri = fmt::format("{}/{}", s3_conf.endpoint, container_name);
+    if (s3_conf.endpoint.find("://") == std::string::npos) {
+        uri = "https://"; + uri;
     }
 
     Azure::Storage::Blobs::BlobClientOptions options;
diff --git a/cloud/src/common/config.h b/cloud/src/common/config.h
index 463adc13332..9e27321ac2c 100644
--- a/cloud/src/common/config.h
+++ b/cloud/src/common/config.h
@@ -290,8 +290,6 @@ CONF_Validator(s3_client_http_scheme, [](const std::string& 
config) -> bool {
     return config == "http" || config == "https";
 });
 
-CONF_Bool(force_azure_blob_global_endpoint, "false");
-
 // Max retry times for object storage request
 CONF_mInt64(max_s3_client_retry, "10");
 
diff --git a/cloud/src/recycler/s3_accessor.cpp 
b/cloud/src/recycler/s3_accessor.cpp
index 1792a81d435..0f2a7776fcc 100644
--- a/cloud/src/recycler/s3_accessor.cpp
+++ b/cloud/src/recycler/s3_accessor.cpp
@@ -372,13 +372,9 @@ int S3Accessor::init() {
         options.Retry.MaxRetries = config::max_s3_client_retry;
         auto cred =
                 
std::make_shared<Azure::Storage::StorageSharedKeyCredential>(conf_.ak, 
conf_.sk);
-        if (config::force_azure_blob_global_endpoint) {
-            uri_ = fmt::format("https://{}.blob.core.windows.net/{}";, 
conf_.ak, conf_.bucket);
-        } else {
-            uri_ = fmt::format("{}/{}", conf_.endpoint, conf_.bucket);
-            if (uri_.find("://") == std::string::npos) {
-                uri_ = "https://"; + uri_;
-            }
+        uri_ = fmt::format("{}/{}", conf_.endpoint, conf_.bucket);
+        if (uri_.find("://") == std::string::npos) {
+            uri_ = "https://"; + uri_;
         }
         uri_ = normalize_http_uri(uri_);
         // In Azure's HTTP requests, all policies in the vector are called in 
a chained manner following the HTTP pipeline approach.
diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java 
b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
index 9f938a81ff0..fa288726acf 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
@@ -3419,13 +3419,27 @@ public class Config extends ConfigBase {
     public static String[] s3_load_endpoint_white_list = {};
 
     @ConfField(mutable = true, description = {
-            "此参数控制是否强制使用 Azure global endpoint。默认值为 false,系统将使用用户指定的 endpoint。"
-            + "如果设置为 true,系统将强制使用 {account}.blob.core.windows.net。",
-            "This parameter controls whether to force the use of the Azure 
global endpoint. "
-            + "The default is false, meaning the system will use the 
user-specified endpoint. "
-            + "If set to true, the system will force the use of 
{account}.blob.core.windows.net."
+            "指定 Azure endpoint 域名后缀白名单(包含 blob 与 dfs),多个值使用逗号分隔。"
+                    + "默认值为 .blob.core.windows.net,.dfs.core.windows.net,"
+                    + ".blob.core.chinacloudapi.cn,.dfs.core.chinacloudapi.cn,"
+                    + 
".blob.core.usgovcloudapi.net,.dfs.core.usgovcloudapi.net,"
+                    + ".blob.core.cloudapi.de,.dfs.core.cloudapi.de。",
+            "The host suffix whitelist for Azure endpoints (both blob and 
dfs), separated by commas. "
+                    + "The default value is 
.blob.core.windows.net,.dfs.core.windows.net,"
+                    + ".blob.core.chinacloudapi.cn,.dfs.core.chinacloudapi.cn,"
+                    + 
".blob.core.usgovcloudapi.net,.dfs.core.usgovcloudapi.net,"
+                    + ".blob.core.cloudapi.de,.dfs.core.cloudapi.de."
     })
-    public static boolean force_azure_blob_global_endpoint = false;
+    public static String[] azure_blob_host_suffixes = {
+            ".blob.core.windows.net",
+            ".dfs.core.windows.net",
+            ".blob.core.chinacloudapi.cn",
+            ".dfs.core.chinacloudapi.cn",
+            ".blob.core.usgovcloudapi.net",
+            ".dfs.core.usgovcloudapi.net",
+            ".blob.core.cloudapi.de",
+            ".dfs.core.cloudapi.de"
+    };
 
     @ConfField(mutable = true, description = {"指定 Jdbc driver url 
白名单,举例:jdbc_driver_url_white_list=a,b,c",
             "the white list for jdbc driver url, if it is empty, no white list 
will be set"
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzureProperties.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzureProperties.java
index b4848aa61b6..a8d6280d377 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzureProperties.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzureProperties.java
@@ -30,6 +30,8 @@ import lombok.Setter;
 import org.apache.hadoop.conf.Configuration;
 
 import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -64,6 +66,7 @@ import java.util.stream.Stream;
 public class AzureProperties extends StorageProperties {
     @Getter
     @ConnectorProperty(names = {"azure.endpoint", "s3.endpoint", 
"AWS_ENDPOINT", "endpoint", "ENDPOINT"},
+            required = false,
             description = "The endpoint of S3.")
     protected String endpoint = "";
 
@@ -135,8 +138,6 @@ public class AzureProperties extends StorageProperties {
         super(Type.AZURE, origProps);
     }
 
-    private static final String AZURE_ENDPOINT_SUFFIX = 
".blob.core.windows.net";
-
     @Override
     public void initNormalizeAndCheckProps() {
         super.initNormalizeAndCheckProps();
@@ -160,7 +161,7 @@ public class AzureProperties extends StorageProperties {
                 .findFirst()
                 .orElse(null);
         if (!Strings.isNullOrEmpty(value)) {
-            return value.endsWith(AZURE_ENDPOINT_SUFFIX);
+            return AzurePropertyUtils.isAzureBlobEndpoint(value);
         }
         return false;
     }
@@ -191,9 +192,12 @@ public class AzureProperties extends StorageProperties {
 
     public static final String AZURE_ENDPOINT_TEMPLATE = 
"https://%s.blob.core.windows.net";;
 
-    public static String formatAzureEndpoint(String endpoint, String 
accessKey) {
-        if (Config.force_azure_blob_global_endpoint) {
-            return String.format(AZURE_ENDPOINT_TEMPLATE, accessKey);
+    public static String formatAzureEndpoint(String endpoint, String 
accountName) {
+        if (Strings.isNullOrEmpty(endpoint)) {
+            if (Strings.isNullOrEmpty(accountName)) {
+                return "";
+            }
+            return String.format(AZURE_ENDPOINT_TEMPLATE, accountName);
         }
         if (endpoint.contains("://")) {
             return endpoint;
@@ -243,13 +247,24 @@ public class AzureProperties extends StorageProperties {
     }
 
     private static void setHDFSAzureAccountKeys(Configuration conf, String 
accountName, String accountKey) {
-        String[] endpoints = {
-                "dfs.core.windows.net",
-                "blob.core.windows.net"
-        };
+        Set<String> endpoints = new LinkedHashSet<>();
+        if (Config.azure_blob_host_suffixes != null) {
+            for (String endpointSuffix : Config.azure_blob_host_suffixes) {
+                if (Strings.isNullOrEmpty(endpointSuffix)) {
+                    continue;
+                }
+                String normalizedEndpoint = 
endpointSuffix.trim().toLowerCase(Locale.ROOT);
+                if (normalizedEndpoint.startsWith(".")) {
+                    normalizedEndpoint = normalizedEndpoint.substring(1);
+                }
+                if (!normalizedEndpoint.isEmpty()) {
+                    endpoints.add(normalizedEndpoint);
+                }
+            }
+        }
         for (String endpoint : endpoints) {
-            String key = String.format("fs.azure.account.key.%s.%s", 
accountName, endpoint);
-            conf.set(key, accountKey);
+            String accountKeyConfig = 
String.format("fs.azure.account.key.%s.%s", accountName, endpoint);
+            conf.set(accountKeyConfig, accountKey);
         }
         conf.set("fs.azure.account.key", accountKey);
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzurePropertyUtils.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzurePropertyUtils.java
index 90152580701..e2d04057f65 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzurePropertyUtils.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/property/storage/AzurePropertyUtils.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.datasource.property.storage;
 
+import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
 import 
org.apache.doris.datasource.property.storage.exception.StoragePropertiesException;
 
@@ -24,11 +25,11 @@ import org.apache.commons.lang3.StringUtils;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Locale;
 import java.util.Map;
 import java.util.regex.Pattern;
 
 public class AzurePropertyUtils {
-
     /**
      * Validates and normalizes an Azure Blob Storage URI into a unified 
{@code s3://}-style format.
      * <p>
@@ -76,6 +77,61 @@ public class AzurePropertyUtils {
     private static final Pattern ONELAKE_PATTERN = Pattern.compile(
             
"abfs[s]?://([^@]+)@([^/]+)\\.dfs\\.fabric\\.microsoft\\.com(/.*)?", 
Pattern.CASE_INSENSITIVE);
 
+    public static boolean isAzureBlobEndpoint(String endpointOrHost) {
+        String host = extractHost(endpointOrHost);
+        if (StringUtils.isBlank(host)) {
+            return false;
+        }
+        String normalizedHost = host.toLowerCase(Locale.ROOT);
+        return matchesAnySuffix(normalizedHost, 
Config.azure_blob_host_suffixes);
+    }
+
+    private static boolean matchesAnySuffix(String normalizedHost, String[] 
suffixes) {
+        if (suffixes == null || suffixes.length == 0) {
+            return false;
+        }
+        for (String suffix : suffixes) {
+            if (matchesSuffix(normalizedHost, suffix)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean matchesSuffix(String normalizedHost, String suffix) 
{
+        if (StringUtils.isBlank(suffix)) {
+            return false;
+        }
+        String normalizedSuffix = suffix.trim().toLowerCase(Locale.ROOT);
+        if (!normalizedSuffix.startsWith(".")) {
+            normalizedSuffix = "." + normalizedSuffix;
+        }
+        return normalizedHost.endsWith(normalizedSuffix);
+    }
+
+    private static String extractHost(String endpointOrHost) {
+        if (StringUtils.isBlank(endpointOrHost)) {
+            return null;
+        }
+        String normalized = endpointOrHost.trim();
+        if (normalized.contains("://")) {
+            try {
+                return new URI(normalized).getHost();
+            } catch (URISyntaxException e) {
+                return null;
+            }
+        }
+        int slashIndex = normalized.indexOf('/');
+        if (slashIndex >= 0) {
+            normalized = normalized.substring(0, slashIndex);
+        }
+        int colonIndex = normalized.indexOf(':');
+        if (colonIndex >= 0) {
+            normalized = normalized.substring(0, colonIndex);
+        }
+        return normalized;
+    }
+
 
     /**
      * Converts an Azure Blob Storage URI into a unified {@code 
s3://<container>/<path>} format.
@@ -137,11 +193,6 @@ public class AzurePropertyUtils {
                     throw new StoragePropertiesException("Invalid Azure HTTPS 
URI, missing host: " + uri);
                 }
 
-                // Typical Azure Blob domain: <account>.blob.core.windows.net
-                if (!host.contains(".blob.core.windows.net")) {
-                    throw new StoragePropertiesException("Not an Azure Blob 
URL: " + uri);
-                }
-
                 // Path usually looks like: /<container>/<path>
                 String[] parts = path.split("/", 3);
                 if (parts.length < 2) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertiesTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertiesTest.java
index 8171f33db40..073d9f361b7 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertiesTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertiesTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.datasource.property.storage;
 
+import org.apache.doris.common.Config;
 import org.apache.doris.common.UserException;
 import 
org.apache.doris.datasource.property.storage.exception.StoragePropertiesException;
 
@@ -213,4 +214,81 @@ public class AzurePropertiesTest {
         
Assertions.assertEquals("https://login.microsoftonline.com/72f988bf-5289-5289-5289-2d7cd011db47/oauth2/token";,
 
hadoopStorageConfig.get("fs.azure.account.oauth2.client.endpoint.onelake.dfs.fabric.microsoft.com"));
 
     }
+
+    @Test
+    public void testGuessIsMeChinaEndpoint() {
+        origProps.put("s3.endpoint", 
"https://mystorageaccount.blob.core.chinacloudapi.cn";);
+        Assertions.assertTrue(AzureProperties.guessIsMe(origProps));
+        origProps.put("s3.endpoint", 
"mystorageaccount.blob.core.chinacloudapi.cn");
+        Assertions.assertTrue(AzureProperties.guessIsMe(origProps));
+    }
+
+    @Test
+    public void testGuessIsMeByProviderWhenEndpointIsUnknown() {
+        origProps.put("s3.endpoint", "https://mystorageaccount.invalid.test";);
+        Assertions.assertFalse(AzureProperties.guessIsMe(origProps));
+        origProps.put("provider", "azure");
+        Assertions.assertTrue(AzureProperties.guessIsMe(origProps));
+    }
+
+    @Test
+    public void testFormatAzureEndpointUsesInputOrDefault() {
+        
Assertions.assertEquals("https://mystorageaccount.blob.core.chinacloudapi.cn";,
+                
AzureProperties.formatAzureEndpoint("mystorageaccount.blob.core.chinacloudapi.cn",
+                        "mystorageaccount"));
+        
Assertions.assertEquals("https://mystorageaccount.blob.core.chinacloudapi.cn";,
+                
AzureProperties.formatAzureEndpoint("https://mystorageaccount.blob.core.chinacloudapi.cn";,
+                        "mystorageaccount"));
+        
Assertions.assertEquals("https://mystorageaccount.blob.core.windows.net";,
+                AzureProperties.formatAzureEndpoint("", "mystorageaccount"));
+        Assertions.assertEquals("", AzureProperties.formatAzureEndpoint("", 
""));
+    }
+
+    @Test
+    public void testDefaultEndpointWhenEndpointNotSet() throws UserException {
+        origProps.put("s3.access_key", "myAzureAccessKey");
+        origProps.put("s3.secret_key", "myAzureSecretKey");
+        origProps.put("provider", "azure");
+
+        AzureProperties azureProperties = (AzureProperties) 
StorageProperties.createPrimary(origProps);
+        
Assertions.assertEquals("https://myAzureAccessKey.blob.core.windows.net";, 
azureProperties.getEndpoint());
+    }
+
+    @Test
+    public void testHadoopStorageConfigContainsChinaCloudAccountKeys() throws 
UserException {
+        origProps.put("s3.endpoint", 
"https://mystorageaccount.blob.core.chinacloudapi.cn";);
+        origProps.put("s3.access_key", "myAzureAccessKey");
+        origProps.put("s3.secret_key", "myAzureSecretKey");
+        origProps.put("provider", "azure");
+
+        AzureProperties azureProperties = (AzureProperties) 
StorageProperties.createPrimary(origProps);
+        Configuration hadoopStorageConfig = 
azureProperties.getHadoopStorageConfig();
+        Assertions.assertEquals("myAzureSecretKey",
+                
hadoopStorageConfig.get("fs.azure.account.key.myAzureAccessKey.blob.core.chinacloudapi.cn"));
+        Assertions.assertEquals("myAzureSecretKey",
+                
hadoopStorageConfig.get("fs.azure.account.key.myAzureAccessKey.dfs.core.chinacloudapi.cn"));
+    }
+
+    @Test
+    public void 
testHadoopStorageConfigContainsCustomAccountKeyEndpointsFromConfig() throws 
UserException {
+        String[] originalAzureBlobHostSuffixes = 
Config.azure_blob_host_suffixes;
+        try {
+            Config.azure_blob_host_suffixes = new String[] 
{"blob.custom.test", ".dfs.custom.test", " "};
+            origProps.put("s3.endpoint", 
"https://mystorageaccount.blob.custom.test";);
+            origProps.put("s3.access_key", "myAzureAccessKey");
+            origProps.put("s3.secret_key", "myAzureSecretKey");
+            origProps.put("provider", "azure");
+
+            AzureProperties azureProperties = (AzureProperties) 
StorageProperties.createPrimary(origProps);
+            Configuration hadoopStorageConfig = 
azureProperties.getHadoopStorageConfig();
+            Assertions.assertEquals("myAzureSecretKey",
+                    
hadoopStorageConfig.get("fs.azure.account.key.myAzureAccessKey.blob.custom.test"));
+            Assertions.assertEquals("myAzureSecretKey",
+                    
hadoopStorageConfig.get("fs.azure.account.key.myAzureAccessKey.dfs.custom.test"));
+            Assertions.assertNull(
+                    
hadoopStorageConfig.get("fs.azure.account.key.myAzureAccessKey.blob.core.windows.net"));
+        } finally {
+            Config.azure_blob_host_suffixes = originalAzureBlobHostSuffixes;
+        }
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertyUtilsTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertyUtilsTest.java
index cbc584d9a10..1965284c3d1 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertyUtilsTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/property/storage/AzurePropertyUtilsTest.java
@@ -17,6 +17,8 @@
 
 package org.apache.doris.datasource.property.storage;
 
+import org.apache.doris.common.Config;
+import org.apache.doris.common.UserException;
 import 
org.apache.doris.datasource.property.storage.exception.StoragePropertiesException;
 
 import org.junit.jupiter.api.Assertions;
@@ -87,6 +89,13 @@ public class AzurePropertyUtilsTest {
         Assertions.assertEquals(expected, 
AzurePropertyUtils.validateAndNormalizeUri(input));
     }
 
+    @Test
+    public void testHttpsChinaUriWithPath() throws Exception {
+        String input = 
"https://account.blob.core.chinacloudapi.cn/container/data/file.parquet";;
+        String expected = "s3://container/data/file.parquet";
+        Assertions.assertEquals(expected, 
AzurePropertyUtils.validateAndNormalizeUri(input));
+    }
+
     @Test
     public void testInvalidAzureScheme() {
         String input = 
"ftp://[email protected]/data/file.txt";;
@@ -109,9 +118,9 @@ public class AzurePropertyUtilsTest {
     }
 
     @Test
-    public void testHttpsUriNotAzureBlob() {
+    public void testHttpsUriNotAzureBlob() throws UserException {
         String input = "https://account.otherdomain.com/container/file.txt";;
-        Assertions.assertThrows(StoragePropertiesException.class, () ->
+        Assertions.assertEquals("s3://container/file.txt",
                 AzurePropertyUtils.validateAndNormalizeUri(input));
     }
 
@@ -121,6 +130,39 @@ public class AzurePropertyUtilsTest {
                 AzurePropertyUtils.validateAndNormalizeUri(" "));
     }
 
+    @Test
+    public void testIsAzureBlobEndpoint() {
+        String[] originalAzureBlobHostSuffixes = 
Config.azure_blob_host_suffixes;
+        try {
+            Config.azure_blob_host_suffixes = new String[] {
+                    ".blob.core.windows.net",
+                    ".dfs.core.windows.net",
+                    ".blob.core.chinacloudapi.cn",
+                    ".dfs.core.chinacloudapi.cn"
+            };
+            
Assertions.assertTrue(AzurePropertyUtils.isAzureBlobEndpoint("https://account.blob.core.windows.net";));
+            
Assertions.assertTrue(AzurePropertyUtils.isAzureBlobEndpoint("account.blob.core.chinacloudapi.cn"));
+            
Assertions.assertTrue(AzurePropertyUtils.isAzureBlobEndpoint("account.dfs.core.chinacloudapi.cn"));
+            
Assertions.assertFalse(AzurePropertyUtils.isAzureBlobEndpoint("https://account.otherdomain.com";));
+        } finally {
+            Config.azure_blob_host_suffixes = originalAzureBlobHostSuffixes;
+        }
+    }
+
+    @Test
+    public void testIsAzureBlobEndpointFromConfig() {
+        String[] originalAzureBlobHostSuffixes = 
Config.azure_blob_host_suffixes;
+        try {
+            Config.azure_blob_host_suffixes = new String[] 
{"blob.custom.test", "dfs.custom.test", " .blob.extra.test "};
+            
Assertions.assertTrue(AzurePropertyUtils.isAzureBlobEndpoint("https://account.blob.custom.test";));
+            
Assertions.assertTrue(AzurePropertyUtils.isAzureBlobEndpoint("account.dfs.custom.test"));
+            
Assertions.assertTrue(AzurePropertyUtils.isAzureBlobEndpoint("account.blob.extra.test"));
+            
Assertions.assertFalse(AzurePropertyUtils.isAzureBlobEndpoint("account.blob.unknown.test"));
+        } finally {
+            Config.azure_blob_host_suffixes = originalAzureBlobHostSuffixes;
+        }
+    }
+
     // ---------- validateAndGetUri Tests ----------
 
     @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to