From 21ffec34999937af4f171967ec99073d6c77f49a Mon Sep 17 00:00:00 2001 From: zhuxiaolong37 Date: Fri, 13 Dec 2024 11:58:13 +0800 Subject: [PATCH] add endpoint resolver --- .../com/aliyun/oss/ClientConfiguration.java | 43 ++++++++ .../aliyun/oss/common/comm/ServiceClient.java | 18 ++++ .../oss/endpoint/DefaultEndpointResolver.java | 19 ++++ .../aliyun/oss/endpoint/EndpointResolver.java | 26 +++++ .../com/aliyun/oss/internal/OSSOperation.java | 8 ++ .../oss/common/comm/EndpointRefreshTest.java | 101 ++++++++++++++++++ .../aliyun/oss/common/comm/OSSClientTest.java | 15 +++ 7 files changed, 230 insertions(+) create mode 100644 src/main/java/com/aliyun/oss/endpoint/DefaultEndpointResolver.java create mode 100644 src/main/java/com/aliyun/oss/endpoint/EndpointResolver.java create mode 100644 src/test/java/com/aliyun/oss/common/comm/EndpointRefreshTest.java diff --git a/src/main/java/com/aliyun/oss/ClientConfiguration.java b/src/main/java/com/aliyun/oss/ClientConfiguration.java index d2d4a44d..1cc32689 100644 --- a/src/main/java/com/aliyun/oss/ClientConfiguration.java +++ b/src/main/java/com/aliyun/oss/ClientConfiguration.java @@ -40,6 +40,8 @@ import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.common.utils.ResourceManager; import com.aliyun.oss.common.utils.VersionInfoUtils; +import com.aliyun.oss.endpoint.DefaultEndpointResolver; +import com.aliyun.oss.endpoint.EndpointResolver; import com.aliyun.oss.internal.OSSConstants; /** @@ -127,6 +129,10 @@ public class ClientConfiguration { private boolean tracerEnabled = false; + private boolean isRefreshEndpointAddr = false; + + private EndpointResolver endpointResolver = new DefaultEndpointResolver(); + public ClientConfiguration() { super(); AppendDefaultExcludeList(this.cnameExcludeList); @@ -991,4 +997,41 @@ public boolean isTracerEnabled() { public void setTracerEnabled(boolean enabled) { this.tracerEnabled = enabled; } + + /** + * Gets the flag of refresh endpoint. + * + * @return True if it's enabled; False if it's disabled. + */ + public boolean isRefreshEndpointAddr() { + return isRefreshEndpointAddr; + } + + /** + * Sets the flag of refresh endpoint. + * + * @param refreshEndpointAddr True if it's enabled; False if it's disabled. + */ + public void setRefreshEndpointAddr(boolean refreshEndpointAddr) { + isRefreshEndpointAddr = refreshEndpointAddr; + } + + /** + * Gets the endpoint resolver. + * + * @return endpoint resolver. + */ + public EndpointResolver getEndpointResolver() { + return endpointResolver; + } + + /** + * Sets the endpoint resolver. + * + * @param endpointResolver + */ + public void setEndpointResolver(EndpointResolver endpointResolver) { + this.endpointResolver = endpointResolver; + } + } diff --git a/src/main/java/com/aliyun/oss/common/comm/ServiceClient.java b/src/main/java/com/aliyun/oss/common/comm/ServiceClient.java index 4a683c2e..71707124 100644 --- a/src/main/java/com/aliyun/oss/common/comm/ServiceClient.java +++ b/src/main/java/com/aliyun/oss/common/comm/ServiceClient.java @@ -28,8 +28,10 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.net.URI; import java.util.List; +import com.aliyun.oss.internal.OSSUtils; import org.apache.http.HttpMessage; import com.aliyun.oss.ClientConfiguration; @@ -120,6 +122,9 @@ private ResponseMessage sendRequestImpl(RequestMessage request, ExecutionContext while (true) { try { if (retries > 0) { + if (config.isRefreshEndpointAddr()) { + refreshEndpointAddr(request); + } pause(retries, retryStrategy); if (requestContent != null && requestContent.markSupported()) { try { @@ -392,4 +397,17 @@ public void setUseChunkEncoding(boolean useChunkEncoding) { this.useChunkEncoding = useChunkEncoding; } } + + public void refreshEndpointAddr(RequestMessage request) + throws ServiceException, ClientException { + String endpoint = ""; + if (config.isSupportCname()){ + endpoint = config.getEndpointResolver().resolveGetServiceApiEndpoint(request.getEndpoint().toString()); + } else { + endpoint = config.getEndpointResolver().resolveGeneralApiEndpoint(request.getEndpoint().toString()); + } + String defaultProto = config.getProtocol().toString(); + URI uri = OSSUtils.toEndpointURI(endpoint, defaultProto); + request.setEndpoint(uri); + } } diff --git a/src/main/java/com/aliyun/oss/endpoint/DefaultEndpointResolver.java b/src/main/java/com/aliyun/oss/endpoint/DefaultEndpointResolver.java new file mode 100644 index 00000000..b3ea42a5 --- /dev/null +++ b/src/main/java/com/aliyun/oss/endpoint/DefaultEndpointResolver.java @@ -0,0 +1,19 @@ + +package com.aliyun.oss.endpoint; + +/** + * default endpoint resolver, just return the api endpoint + * the dns resolve will be implemented by http library. + */ +public class DefaultEndpointResolver implements EndpointResolver { + + @Override + public String resolveGeneralApiEndpoint(String generalApiEndpoint) { + return generalApiEndpoint; + } + + @Override + public String resolveGetServiceApiEndpoint(String getServiceApiEndpoint) { + return getServiceApiEndpoint; + } +} diff --git a/src/main/java/com/aliyun/oss/endpoint/EndpointResolver.java b/src/main/java/com/aliyun/oss/endpoint/EndpointResolver.java new file mode 100644 index 00000000..e77df5cf --- /dev/null +++ b/src/main/java/com/aliyun/oss/endpoint/EndpointResolver.java @@ -0,0 +1,26 @@ +package com.aliyun.oss.endpoint; + +/** + * resolve the endpoint like dns. + * + */ + +public interface EndpointResolver { + /** + * return the general api endpoint, the result can be ip or ip:port. if you don't do + * anything like DefaultEndpointResolver. the http library will implement the dns resolve. + * + * @param generalApiEndpoint + * @return the endpoint addr + */ + public String resolveGeneralApiEndpoint(String generalApiEndpoint); + + /** + * return the get service api endpoint, the result can be ip or ip:port. if you don't do + * anything like DefaultEndpointResolver. the http library will implement the dns resolve. + * + * @param getServiceApiEndpoint + * @return the endpoint + */ + public String resolveGetServiceApiEndpoint(String getServiceApiEndpoint); +} diff --git a/src/main/java/com/aliyun/oss/internal/OSSOperation.java b/src/main/java/com/aliyun/oss/internal/OSSOperation.java index a73eec7f..98760d05 100644 --- a/src/main/java/com/aliyun/oss/internal/OSSOperation.java +++ b/src/main/java/com/aliyun/oss/internal/OSSOperation.java @@ -91,6 +91,14 @@ public URI getEndpoint() { public URI getEndpoint(WebServiceRequest request) { String reqEndpoint = request.getEndpoint(); + if (client.getClientConfiguration().isRefreshEndpointAddr()) { + if (client.getClientConfiguration().isSupportCname()){ + reqEndpoint = client.getClientConfiguration().getEndpointResolver().resolveGetServiceApiEndpoint(reqEndpoint); + } else { + reqEndpoint = client.getClientConfiguration().getEndpointResolver().resolveGeneralApiEndpoint(reqEndpoint); + } + } + if (reqEndpoint == null) { return getEndpoint(); diff --git a/src/test/java/com/aliyun/oss/common/comm/EndpointRefreshTest.java b/src/test/java/com/aliyun/oss/common/comm/EndpointRefreshTest.java new file mode 100644 index 00000000..0aa9a89e --- /dev/null +++ b/src/test/java/com/aliyun/oss/common/comm/EndpointRefreshTest.java @@ -0,0 +1,101 @@ +package com.aliyun.oss.common.comm; + +import com.aliyun.oss.*; +import com.aliyun.oss.common.auth.Credentials; +import com.aliyun.oss.common.auth.DefaultCredentialProvider; +import com.aliyun.oss.common.auth.DefaultCredentials; +import com.aliyun.oss.endpoint.EndpointResolver; +import com.aliyun.oss.integrationtests.TestBase; +import com.aliyun.oss.integrationtests.TestConfig; +import junit.framework.Assert; +import org.junit.Test; + +public class EndpointRefreshTest extends TestBase { + + @Test + public void testEndpointRefresh() { + class CustomEndpointResolver implements EndpointResolver { + private String endpoint = null; + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + @Override + public String resolveGeneralApiEndpoint(String generalApiEndpoint) { + return this.endpoint; + } + + @Override + public String resolveGetServiceApiEndpoint(String getServiceApiEndpoint) { + return this.endpoint; + } + } + + ClientBuilderConfiguration conf = new ClientBuilderConfiguration(); + Credentials credentials = new DefaultCredentials(TestConfig.OSS_TEST_ACCESS_KEY_ID, TestConfig.OSS_TEST_ACCESS_KEY_SECRET); + OSS client = new OSSClient(TestConfig.OSS_TEST_ENDPOINT, new DefaultCredentialProvider(credentials), conf); + Assert.assertEquals(TestConfig.OSS_TEST_ENDPOINT, ((OSSClient) client).getEndpoint().toString()); + + CustomEndpointResolver customEndpointResolver = new CustomEndpointResolver(); + + // Custom Domain + customEndpointResolver.setEndpoint("www.abbbc.com"); + conf.setSupportCname(true); + conf.setRefreshEndpointAddr(true); + conf.setEndpointResolver(customEndpointResolver); + + try { + client.getObject("bucket","object"); + System.out.println("ok"); + } catch (ClientException e) { + Assert.assertEquals("www.abbbc.com\n" + + "[ErrorCode]: UnknownHost\n" + + "[RequestId]: Unknown", e.getMessage()); + } + + // ip + customEndpointResolver.setEndpoint("127.0.0.1"); + conf.setSupportCname(true); + conf.setEndpointResolver(customEndpointResolver); + + try { + client.getObject("bucket","object"); + System.out.println("ok"); + } catch (ClientException e) { + Assert.assertEquals("Connect to 127.0.0.1:80 [/127.0.0.1] failed: Connection refused: connect\n" + + "[ErrorCode]: SocketException\n" + + "[RequestId]: Unknown", e.getMessage()); + } + + // ip:port + customEndpointResolver.setEndpoint("127.0.0.1:8080"); + conf.setSupportCname(true); + conf.setEndpointResolver(customEndpointResolver); + + try { + client.getObject("bucket","object"); + System.out.println("ok"); + } catch (ClientException e) { + Assert.assertEquals("Connect to 127.0.0.1:8080 [/127.0.0.1] failed: Connection refused: connect\n" + + "[ErrorCode]: SocketException\n" + + "[RequestId]: Unknown", e.getMessage()); + } + + // bucket.Domain + conf.setSupportCname(false); + customEndpointResolver.setEndpoint("aaa.aliyuncs.com"); + conf.setEndpointResolver(customEndpointResolver); + try { + client.getObject("bucket","object"); + } catch (ClientException e) { + Assert.assertEquals("aaa.aliyuncs.com\n" + + "[ErrorCode]: UnknownHost\n" + + "[RequestId]: Unknown", e.getMessage()); + } + } +} diff --git a/src/test/java/com/aliyun/oss/common/comm/OSSClientTest.java b/src/test/java/com/aliyun/oss/common/comm/OSSClientTest.java index 9f206be3..105c54e5 100644 --- a/src/test/java/com/aliyun/oss/common/comm/OSSClientTest.java +++ b/src/test/java/com/aliyun/oss/common/comm/OSSClientTest.java @@ -30,6 +30,8 @@ import com.aliyun.oss.common.auth.Credentials; import com.aliyun.oss.common.auth.CredentialsProvider; import com.aliyun.oss.common.auth.DefaultCredentialProvider; +import com.aliyun.oss.endpoint.DefaultEndpointResolver; +import com.aliyun.oss.endpoint.EndpointResolver; import com.aliyun.oss.internal.OSSConstants; import com.aliyun.oss.internal.RequestParameters; import com.aliyun.oss.model.GetObjectRequest; @@ -482,5 +484,18 @@ public void testExtractSettingFromEndpoint() { Assert.assertEquals("region", clientImpl.getObjectOperation().getRegion()); Assert.assertEquals("oss-cloudbox", clientImpl.getObjectOperation().getProduct()); } + + @Test + public void testConfigurationWithEndpointResolver() { + ClientConfiguration clientConfiguration = new ClientConfiguration(); + + clientConfiguration.setRefreshEndpointAddr(true); + Assert.assertEquals(true, clientConfiguration.isRefreshEndpointAddr()); + + DefaultEndpointResolver defaultEndpointResolver = new DefaultEndpointResolver(); + clientConfiguration.setEndpointResolver(defaultEndpointResolver); + Assert.assertEquals(defaultEndpointResolver, clientConfiguration.getEndpointResolver()); + } + }