From 07e4b3098dfc007398bd255c45554281fab4a62e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 11:46:12 +0800 Subject: [PATCH 1/8] Add async method --- aliyun-net-sdk-core/AcsRequest.cs | 2 +- .../Provider/AccessKeyCredentialProvider.cs | 10 +- .../AlibabaCloudCredentialsProvider.cs | 7 +- .../Provider/BearerTokenCredentialProvider.cs | 10 +- .../DefaultCredentialProvider.Async.cs | 243 +++++++++++++++++ .../Provider/DefaultCredentialProvider.cs | 2 +- ...MetadataServiceCredentialsFetcher.Async.cs | 130 +++++++++ .../ECSMetadataServiceCredentialsFetcher.cs | 4 +- .../InstanceProfileCredentialsProvider.cs | 40 +++ .../Provider/RsaKeyPairCredentialProvider.cs | 32 ++- ...STSAssumeRoleSessionCredentialsProvider.cs | 37 ++- .../Provider/StaticCredentialsProvider.cs | 9 +- .../Auth/Provider/StsCredentialProvider.cs | 10 +- aliyun-net-sdk-core/DefaultAcsClient.Async.cs | 257 ++++++++++++++++++ aliyun-net-sdk-core/DefaultAcsClient.cs | 2 +- .../Http/HttpResponse.Async.cs | 218 +++++++++++++++ aliyun-net-sdk-core/Http/HttpResponse.cs | 22 +- aliyun-net-sdk-core/IAcsClient.Async.cs | 92 +++++++ aliyun-net-sdk-core/IAcsClient.cs | 4 +- aliyun-net-sdk-core/Profile/DefaultProfile.cs | 21 +- aliyun-net-sdk-core/Profile/IClientProfile.cs | 9 +- .../Regions/DescribeEndpointService.cs | 9 +- .../Regions/DescribeEndpointServiceImpl.cs | 61 ++++- .../Endpoints/EndpointResolve.Async.cs | 133 +++++++++ .../Regions/Endpoints/EndpointResolve.cs | 4 +- .../Regions/IEndpointsProvider.cs | 12 +- .../Regions/InternalEndpointsParser.cs | 16 +- .../Regions/RemoteEndpointsParser.cs | 39 ++- .../aliyun-net-sdk-core.vs2017.csproj | 9 +- .../Timeout/TimeoutTest.Async.cs | 86 ++++++ 30 files changed, 1475 insertions(+), 55 deletions(-) create mode 100644 aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs create mode 100644 aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs create mode 100644 aliyun-net-sdk-core/DefaultAcsClient.Async.cs create mode 100644 aliyun-net-sdk-core/Http/HttpResponse.Async.cs create mode 100644 aliyun-net-sdk-core/IAcsClient.Async.cs create mode 100644 aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs create mode 100644 aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs diff --git a/aliyun-net-sdk-core/AcsRequest.cs b/aliyun-net-sdk-core/AcsRequest.cs index 4ecfffb38c..2c32a2e118 100644 --- a/aliyun-net-sdk-core/AcsRequest.cs +++ b/aliyun-net-sdk-core/AcsRequest.cs @@ -21,7 +21,7 @@ using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; - +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Regions; diff --git a/aliyun-net-sdk-core/Auth/Provider/AccessKeyCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/AccessKeyCredentialProvider.cs index 09fc87b6ca..132b196ac8 100644 --- a/aliyun-net-sdk-core/Auth/Provider/AccessKeyCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/AccessKeyCredentialProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,6 +17,9 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; + namespace Aliyun.Acs.Core.Auth { /// @@ -35,5 +38,10 @@ public AlibabaCloudCredentials GetCredentials() { return accessKeyCredential; } + + public Task GetCredentialsAsync(CancellationToken cancellationToken) + { + return Task.FromResult(accessKeyCredential); + } } } diff --git a/aliyun-net-sdk-core/Auth/Provider/AlibabaCloudCredentialsProvider.cs b/aliyun-net-sdk-core/Auth/Provider/AlibabaCloudCredentialsProvider.cs index c01ee3e5df..5b5e397198 100644 --- a/aliyun-net-sdk-core/Auth/Provider/AlibabaCloudCredentialsProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/AlibabaCloudCredentialsProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,10 +17,15 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; + namespace Aliyun.Acs.Core.Auth { public interface AlibabaCloudCredentialsProvider { AlibabaCloudCredentials GetCredentials(); + + Task GetCredentialsAsync(CancellationToken cancellationToken); } } diff --git a/aliyun-net-sdk-core/Auth/Provider/BearerTokenCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/BearerTokenCredentialProvider.cs index 5507a2bbfb..65555ae520 100644 --- a/aliyun-net-sdk-core/Auth/Provider/BearerTokenCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/BearerTokenCredentialProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,6 +17,9 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; + namespace Aliyun.Acs.Core.Auth { public class BearerTokenCredentialProvider : AlibabaCloudCredentialsProvider @@ -32,5 +35,10 @@ public AlibabaCloudCredentials GetCredentials() { return bearerTokenCredential; } + + public Task GetCredentialsAsync(CancellationToken cancellationToken) + { + return Task.FromResult(bearerTokenCredential); + } } } diff --git a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs new file mode 100644 index 0000000000..13edc850ee --- /dev/null +++ b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs @@ -0,0 +1,243 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Exceptions; +using Aliyun.Acs.Core.Profile; +using Aliyun.Acs.Core.Utils; + +namespace Aliyun.Acs.Core.Auth.Provider +{ + public partial class DefaultCredentialProvider + { + public async Task GetAlibabaCloudClientCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + var credential = await GetEnvironmentAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false) ?? + await GetCredentialFileAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false) ?? + await GetInstanceRamRoleAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); + + if (credential == null) + { + throw new ClientException("There is no credential chain can use."); + } + + return credential; + } + + public async Task GetEnvironmentAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + if (null == accessKeyId || null == accessKeySecret) + { + return null; + } + + if (accessKeyId.Equals("") || accessKeySecret.Equals("")) + { + throw new ClientException( + "Environment credential variable 'ALIBABA_CLOUD_ACCESS_KEY_*' cannot be empty"); + } + + return defaultProfile.DefaultClientName.Equals("default") ? await GetAccessKeyCredentialAsync(cancellationToken).ConfigureAwait(false) : null; + } + + public async Task GetCredentialFileAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + if (null == credentialFileLocation) + { + credentialFileLocation = GetHomePath(); + var slash = EnvironmentUtil.GetOSSlash(); + var fileLocation = EnvironmentUtil.GetComposedPath(credentialFileLocation, slash); + + if (File.Exists(fileLocation)) + { + credentialFileLocation = fileLocation; + } + else + { + return null; + } + } + + if (credentialFileLocation.Equals("")) + { + throw new ClientException( + "Credentials file environment variable 'ALIBABA_CLOUD_CREDENTIALS_FILE' cannot be empty"); + } + + var iniReader = new IniReader(credentialFileLocation); + var sectionNameList = iniReader.GetSections(); + + if (null != defaultProfile.DefaultClientName) + { + var userDefineSectionNode = defaultProfile.DefaultClientName; + + var iniKeyTypeValue = iniReader.GetValue("type", userDefineSectionNode); + + if (iniKeyTypeValue.Equals("access_key")) + { + accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); + accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); + regionId = iniReader.GetValue("region_id", userDefineSectionNode); + + return await GetAccessKeyCredentialAsync().ConfigureAwait(false); + } + + if (iniKeyTypeValue.Equals("ecs_ram_role")) + { + roleName = iniReader.GetValue("role_name", userDefineSectionNode); + regionId = iniReader.GetValue("region_id", userDefineSectionNode); + + return await GetInstanceRamRoleAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); + } + + if (iniKeyTypeValue.Equals("ram_role_arn")) + { + accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); + accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); + roleArn = iniReader.GetValue("role_arn", userDefineSectionNode); + + return await GetRamRoleArnAlibabaCloudCredentialAsync().ConfigureAwait(false); + } + + if (iniKeyTypeValue.Equals("rsa_key_pair")) + { + publicKeyId = iniReader.GetValue("public_key_id", userDefineSectionNode); + privateKeyFile = iniReader.GetValue("private_key_file", userDefineSectionNode); + + return await GetRsaKeyPairAlibabaCloudCredentialAsync().ConfigureAwait(false); + } + } + else + { + foreach (var sectionItem in sectionNameList) + { + if (!sectionItem.Equals("default")) + { + continue; + } + + accessKeyId = iniReader.GetValue("access_key_id", "default"); + accessKeySecret = iniReader.GetValue("access_key_secret", "default"); + regionId = iniReader.GetValue("region_id", "default"); + + return await GetAccessKeyCredentialAsync().ConfigureAwait(false); + } + } + + return null; + } + + public virtual Task GetInstanceRamRoleAlibabaCloudCredentialAsync(CancellationToken cancellationToken) + { + if (null == regionId || regionId.Equals("")) + { + throw new ClientException("RegionID cannot be null or empty."); + } + + if (!defaultProfile.DefaultClientName.Equals("default")) + { + return null; + } + + InstanceProfileCredentialsProvider instanceProfileCredentialProvider; + if (null != alibabaCloudCredentialProvider) + { + instanceProfileCredentialProvider = + (InstanceProfileCredentialsProvider)alibabaCloudCredentialProvider; + } + else + { + instanceProfileCredentialProvider = new InstanceProfileCredentialsProvider(roleName); + } + + return instanceProfileCredentialProvider.GetCredentialsAsync(cancellationToken); + } + + public Task GetAccessKeyCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || + string.IsNullOrEmpty(regionId)) + { + throw new ClientException("Missing required variable option for 'default Client'"); + } + + var accessKeyCredentialProvider = + new AccessKeyCredentialProvider(accessKeyId, accessKeySecret); + + return accessKeyCredentialProvider.GetCredentialsAsync(cancellationToken); + } + + public virtual Task GetRamRoleArnAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || + string.IsNullOrEmpty(regionId)) + { + throw new ClientException("Missing required variable option for 'default Client'"); + } + + var credential = new BasicSessionCredentials(accessKeyId, accessKeySecret, + STSAssumeRoleSessionCredentialsProvider.GetNewRoleSessionName(), + 3600 + ); + var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); + + STSAssumeRoleSessionCredentialsProvider stsAsssumeRoleSessionCredentialProvider; + + if (null != alibabaCloudCredentialProvider) + { + stsAsssumeRoleSessionCredentialProvider = + (STSAssumeRoleSessionCredentialsProvider)alibabaCloudCredentialProvider; + } + else + { + stsAsssumeRoleSessionCredentialProvider = + new STSAssumeRoleSessionCredentialsProvider(credential, roleArn, profile); + } + + return stsAsssumeRoleSessionCredentialProvider.GetCredentialsAsync(cancellationToken); + } + + public virtual Task GetRsaKeyPairAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + if (string.IsNullOrEmpty(publicKeyId) || string.IsNullOrEmpty(privateKeyFile) || + string.IsNullOrEmpty(regionId)) + { + throw new ClientException("Missing required variable option for 'default Client'"); + } + + var rsaKeyPairCredential = new KeyPairCredentials(publicKeyId, privateKeyFile); + var profile = DefaultProfile.GetProfile(regionId, publicKeyId, privateKeyFile); + + RsaKeyPairCredentialProvider rsaKeyPairCredentialProvider; + + if (null != alibabaCloudCredentialProvider) + { + rsaKeyPairCredentialProvider = (RsaKeyPairCredentialProvider)alibabaCloudCredentialProvider; + } + else + { + rsaKeyPairCredentialProvider = new RsaKeyPairCredentialProvider(rsaKeyPairCredential, profile); + } + + return rsaKeyPairCredentialProvider.GetCredentialsAsync(cancellationToken); + } + } +} diff --git a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs index 235c4a849a..29f4b73143 100644 --- a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs @@ -25,7 +25,7 @@ namespace Aliyun.Acs.Core.Auth.Provider { - public class DefaultCredentialProvider + public partial class DefaultCredentialProvider { private static IClientProfile defaultProfile; diff --git a/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs b/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs new file mode 100644 index 0000000000..685fa5c4f9 --- /dev/null +++ b/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Exceptions; +using Aliyun.Acs.Core.Http; +using Aliyun.Acs.Core.Reader; +using Aliyun.Acs.Core.Utils; + +namespace Aliyun.Acs.Core.Auth +{ + public partial class ECSMetadataServiceCredentialsFetcher + { + + public async Task GetCredentialsAsync(CancellationToken cancellationToken) + { + return await FetchAsync(cancellationToken).ConfigureAwait(false); + } + + public async Task GetMetadataAsync(CancellationToken cancellationToken) + { + var request = new HttpRequest(credentialUrl); + request.Method = MethodType.GET; + request.SetConnectTimeoutInMilliSeconds(connectionTimeoutInMilliseconds); + + HttpResponse response; + try + { + response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); + } + catch (WebException e) + { + throw new ClientException("Failed to connect ECS Metadata Service: " + e); + } + + if (response.Status != 200) + { + throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG + " HttpCode=" + response.Status); + } + + return Encoding.UTF8.GetString(response.Content); + } + + public virtual async Task FetchAsync(CancellationToken cancellationToken) + { + Dictionary dic; + try + { + var jsonContent = await GetMetadataAsync(cancellationToken).ConfigureAwait(false); + + IReader reader = new JsonReader(); + dic = reader.Read(jsonContent, ""); + } + catch (Exception e) + { + throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG + " Reason: " + e); + } + + if ( + DictionaryUtil.Get(dic, ".Code") == null || + DictionaryUtil.Get(dic, ".AccessKeyId") == null || + DictionaryUtil.Get(dic, ".AccessKeySecret") == null || + DictionaryUtil.Get(dic, ".SecurityToken") == null || + DictionaryUtil.Get(dic, ".Expiration") == null + ) + { + throw new ClientException("Invalid json got from ECS Metadata service."); + } + + if (!"Success".Equals(DictionaryUtil.Get(dic, ".Code"))) + { + throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG); + } + + return new InstanceProfileCredentials( + DictionaryUtil.Get(dic, ".AccessKeyId"), + DictionaryUtil.Get(dic, ".AccessKeySecret"), + DictionaryUtil.Get(dic, ".SecurityToken"), + DictionaryUtil.Get(dic, ".Expiration"), + DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS + ); + } + + public async Task FetchAsync(int retryTimes, CancellationToken cancellationToken) + { + for (var i = 0; i <= retryTimes; i++) + { + try + { + return await FetchAsync(cancellationToken).ConfigureAwait(false); + } + catch (ClientException e) + { + if (i == retryTimes) + { + throw new ClientException(e.ErrorCode, e.ErrorMessage); + } + } + } + + throw new ClientException("Failed to connect ECS Metadata Service: Max retry times exceeded."); + } + + public virtual Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken) + { + return HttpResponse.GetResponseAsync(request, cancellationToken); + } + } +} diff --git a/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs b/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs index 3de0ff3d0a..edecf2a2a4 100644 --- a/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs +++ b/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs @@ -21,7 +21,7 @@ using System.Collections.Generic; using System.Net; using System.Text; - +using System.Threading.Tasks; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Reader; @@ -29,7 +29,7 @@ namespace Aliyun.Acs.Core.Auth { - public class ECSMetadataServiceCredentialsFetcher : AlibabaCloudCredentialsProvider + public partial class ECSMetadataServiceCredentialsFetcher : AlibabaCloudCredentialsProvider { private const string URL_IN_ECS_METADATA = "/latest/meta-data/ram/security-credentials/"; private const int DEFAULT_TIMEOUT_IN_MILLISECONDS = 5000; diff --git a/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs b/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs index b5084ca889..63df830752 100644 --- a/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs @@ -17,6 +17,8 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Utils; @@ -77,6 +79,44 @@ public virtual AlibabaCloudCredentials GetCredentials() return credentials; } + public async Task GetCredentialsAsync(CancellationToken cancellationToken) + { + try + { + if (credentials == null) + { + credentials = await fetcher.FetchAsync(maxRetryTimes, cancellationToken).ConfigureAwait(false); + } + + if (credentials.IsExpired()) + { + throw new ClientException("SDK.SessionTokenExpired", "Current session token has expired."); + } + + if (!credentials.WillSoonExpire() || !credentials.ShouldRefresh()) + { + return credentials; + } + + credentials = await fetcher.FetchAsync(cancellationToken).ConfigureAwait(false); + return credentials; + } + catch (ClientException ex) + { + if (ex.ErrorCode.Equals("SDK.SessionTokenExpired") && + ex.ErrorMessage.Equals("Current session token has expired.")) + { + CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); + throw new ClientException(ex.ErrorCode, ex.ErrorMessage); + } + + // Use the current expiring session token and wait for next round + credentials.SetLastFailedRefreshTime(); + } + + return credentials; + } + public void withFetcher(ECSMetadataServiceCredentialsFetcher fetcher) { this.fetcher = fetcher; diff --git a/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs index 1cd4e3a575..7446cb7524 100644 --- a/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,6 +17,8 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth.Sts; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Profile; @@ -52,6 +54,16 @@ public virtual AlibabaCloudCredentials GetCredentials() return basicSessionCredentials; } + public async Task GetCredentialsAsync(CancellationToken cancellationToken) + { + if (basicSessionCredentials == null || basicSessionCredentials.WillSoonExpire()) + { + basicSessionCredentials = await GetNewSessionCredentialsAsync().ConfigureAwait(false); + } + + return basicSessionCredentials; + } + public void WithDurationSeconds(long seconds) { sessionDurationSeconds = seconds; @@ -79,5 +91,23 @@ private BasicSessionCredentials GetNewSessionCredentials() null, sessionDurationSeconds ); } + + private async Task GetNewSessionCredentialsAsync() + { + var request = new GetSessionAccessKeyRequest + { + PublicKeyId = rsaKeyPairCredential.GetAccessKeyId(), + DurationSeconds = (int)sessionDurationSeconds, + Protocol = ProtocolType.HTTPS + }; + + var response = await stsClient.GetAcsResponseAsync(request).ConfigureAwait(false); + + return new BasicSessionCredentials( + response.SessionAccesskey.SessionAccessKeyId, + response.SessionAccesskey.SessionAccessKeySecert, + null, sessionDurationSeconds + ); + } } } diff --git a/aliyun-net-sdk-core/Auth/Provider/STSAssumeRoleSessionCredentialsProvider.cs b/aliyun-net-sdk-core/Auth/Provider/STSAssumeRoleSessionCredentialsProvider.cs index ed4705100a..b63f2cbbd4 100644 --- a/aliyun-net-sdk-core/Auth/Provider/STSAssumeRoleSessionCredentialsProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/STSAssumeRoleSessionCredentialsProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,7 +18,8 @@ */ using System; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth.Sts; using Aliyun.Acs.Core.Profile; using Aliyun.Acs.Core.Utils; @@ -111,6 +112,16 @@ public AlibabaCloudCredentials GetCredentials() return credentials; } + public async Task GetCredentialsAsync(CancellationToken cancellationToken) + { + if (credentials == null || credentials.WillSoonExpire()) + { + credentials = await GetNewSessionCredentialsAsync().ConfigureAwait(false); + } + + return credentials; + } + public void WithRoleSessionName(string roleSessionName) { this.roleSessionName = roleSessionName; @@ -158,5 +169,27 @@ private BasicSessionCredentials GetNewSessionCredentials() response.Credentials.SecurityToken, roleSessionDurationSeconds ); } + + private async Task GetNewSessionCredentialsAsync() + { + var assumeRoleRequest = new AssumeRoleRequest + { + RoleArn = roleArn, + RoleSessionName = roleSessionName, + DurationSeconds = roleSessionDurationSeconds + }; + + if (!string.IsNullOrEmpty(policy)) + { + assumeRoleRequest.Policy = policy; + } + + var response = await stsClient.GetAcsResponseAsync(assumeRoleRequest).ConfigureAwait(false); + return new BasicSessionCredentials( + response.Credentials.AccessKeyId, + response.Credentials.AccessKeySecret, + response.Credentials.SecurityToken, roleSessionDurationSeconds + ); + } } } diff --git a/aliyun-net-sdk-core/Auth/Provider/StaticCredentialsProvider.cs b/aliyun-net-sdk-core/Auth/Provider/StaticCredentialsProvider.cs index 536c9f2e67..4eeaab6445 100644 --- a/aliyun-net-sdk-core/Auth/Provider/StaticCredentialsProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/StaticCredentialsProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,6 +17,8 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Profile; namespace Aliyun.Acs.Core.Auth @@ -52,5 +54,10 @@ public AlibabaCloudCredentials GetCredentials() { return credentials; } + + public Task GetCredentialsAsync(CancellationToken cancellationToken) + { + return Task.FromResult(credentials); + } } } diff --git a/aliyun-net-sdk-core/Auth/Provider/StsCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/StsCredentialProvider.cs index e8e3052431..9def151ddd 100644 --- a/aliyun-net-sdk-core/Auth/Provider/StsCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/StsCredentialProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,6 +17,9 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; + namespace Aliyun.Acs.Core.Auth { public class StsCredentialProvider : AlibabaCloudCredentialsProvider @@ -32,5 +35,10 @@ public AlibabaCloudCredentials GetCredentials() { return stsCredential; } + + public Task GetCredentialsAsync(CancellationToken cancellationToken) + { + return Task.FromResult(stsCredential); + } } } diff --git a/aliyun-net-sdk-core/DefaultAcsClient.Async.cs b/aliyun-net-sdk-core/DefaultAcsClient.Async.cs new file mode 100644 index 0000000000..bc93643b51 --- /dev/null +++ b/aliyun-net-sdk-core/DefaultAcsClient.Async.cs @@ -0,0 +1,257 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Auth; +using Aliyun.Acs.Core.Auth.Provider; +using Aliyun.Acs.Core.Exceptions; +using Aliyun.Acs.Core.Http; +using Aliyun.Acs.Core.Profile; +using Aliyun.Acs.Core.Regions; +using Aliyun.Acs.Core.Retry; +using Aliyun.Acs.Core.Retry.Condition; +using Aliyun.Acs.Core.Utils; + +namespace Aliyun.Acs.Core +{ + public partial class DefaultAcsClient + { + public async Task GetAcsResponseAsync(AcsRequest request, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetAcsResponseAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, autoRetry, maxRetryNumber, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetAcsResponseAsync(AcsRequest request, IClientProfile profile, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, profile, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetAcsResponseAsync(AcsRequest request, string regionId, Credential credential, CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, regionId, credential, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetCommonResponseAsync(CommonRequest request, CancellationToken cancellationToken = default(CancellationToken)) + { + var httpResponse = await DoActionAsync(request.BuildRequest(), cancellationToken).ConfigureAwait(false); + string data = null; + if (httpResponse.Content != null) + { + data = Encoding.UTF8.GetString(httpResponse.Content); + } + + var response = new CommonResponse + { + Data = data, + HttpResponse = httpResponse, + HttpStatus = httpResponse.Status + }; + + return response; + } + + public Task DoActionAsync(AcsRequest request, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse + { + return DoActionAsync(request, AutoRetry, MaxRetryNumber, clientProfile, cancellationToken); + } + + public Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse + { + return DoActionAsync(request, autoRetry, maxRetryNumber, clientProfile, cancellationToken); + } + + public Task DoActionAsync(AcsRequest request, IClientProfile profile, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse + { + return DoActionAsync(request, AutoRetry, MaxRetryNumber, profile, cancellationToken); + } + + public async Task DoActionAsync(AcsRequest request, string regionId, Credential credential, CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse + { + var signer = Signer.GetSigner(new LegacyCredentials(credential)); + FormatType? format = null; + if (null == request.RegionId) + { + request.RegionId = regionId; + } + + if (request.ProductDomain == null) + { + request.ProductDomain = EndpointUserConfig.GetProductDomain(request.Product, request.RegionId); + if (request.ProductDomain == null) + { + request.SetProductDomain(); + } + } + + List endpoints = null; + if (null != clientProfile) + { + format = clientProfile.GetFormat(); + if (request.ProductDomain == null) + { + endpoints = await clientProfile.GetEndpointsAsync(request.Product, request.RegionId, request.LocationProduct, + request.LocationEndpointType, cancellationToken).ConfigureAwait(false); + } + } + + return await DoActionAsync(request, AutoRetry, MaxRetryNumber, request.RegionId, credential, signer, format, endpoints, cancellationToken).ConfigureAwait(false); + } + + public async Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, IClientProfile profile, CancellationToken cancellationToken) where T : AcsResponse + { + if (null == profile) + { + throw new ClientException("SDK.InvalidProfile", "No active profile found."); + } + + var retry = autoRetry; + var retryNumber = maxRetryNumber; + var region = profile.GetRegionId(); + if (null == request.RegionId) + { + request.RegionId = region; + } + + if (request.ProductDomain == null) + { + request.ProductDomain = EndpointUserConfig.GetProductDomain(request.Product, request.RegionId); + if (request.ProductDomain == null) + { + request.SetProductDomain(); + } + } + + var credentials = await credentialsProvider.GetCredentialsAsync(cancellationToken).ConfigureAwait(false); + if (credentials == null) + { + credentials = await new DefaultCredentialProvider().GetAlibabaCloudClientCredentialAsync(cancellationToken).ConfigureAwait(false); + } + + var signer = Signer.GetSigner(credentials); + var format = profile.GetFormat(); + List endpoints = null; + + if (request.ProductDomain == null) + { + endpoints = await clientProfile.GetEndpointsAsync(request.Product, request.RegionId, + request.LocationProduct, + request.LocationEndpointType, cancellationToken).ConfigureAwait(false); + } + + return await DoActionAsync(request, retry, retryNumber, request.RegionId, credentials, signer, format, endpoints, cancellationToken).ConfigureAwait(false); + } + + public Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, string regionId, + Credential credential, Signer signer, FormatType? format, List endpoints, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse + { + return DoActionAsync(request, autoRetry, maxRetryNumber, regionId, new LegacyCredentials(credential), signer, + format, endpoints, cancellationToken); + } + + public virtual async Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, + string regionId, + AlibabaCloudCredentials credentials, Signer signer, FormatType? format, List endpoints, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse + { + var httpStatusCode = ""; + var retryAttemptTimes = 0; + ClientException exception; + RetryPolicyContext retryPolicyContext; + + do + { + try + { + var watch = Stopwatch.StartNew(); + + FormatType? requestFormatType = request.AcceptFormat; + format = requestFormatType; + + var domain = request.ProductDomain ?? + Endpoint.FindProductDomain(regionId, request.Product, endpoints); + + if (null == domain) + { + throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access."); + } + + var userAgent = UserAgent.Resolve(request.GetSysUserAgentConfig(), userAgentConfig); + DictionaryUtil.Add(request.Headers, "User-Agent", userAgent); + DictionaryUtil.Add(request.Headers, "x-acs-version", request.Version); + if (!string.IsNullOrWhiteSpace(request.ActionName)) + { + DictionaryUtil.Add(request.Headers, "x-acs-action", request.ActionName); + } + var httpRequest = request.SignRequest(signer, credentials, format, domain); + ResolveTimeout(httpRequest, request.Product, request.Version, request.ActionName); + SetHttpsInsecure(IgnoreCertificate); + ResolveProxy(httpRequest, request); + var response = await GetResponseAsync(httpRequest, cancellationToken).ConfigureAwait(false); + + httpStatusCode = response.Status.ToString(); + PrintHttpDebugMsg(request, response); + watch.Stop(); + CommonLog.ExecuteTime = watch.ElapsedMilliseconds; + return response; + } + catch (ClientException ex) + { + retryPolicyContext = new RetryPolicyContext(ex, httpStatusCode, retryAttemptTimes, request.Product, + request.Version, + request.ActionName, RetryCondition.BlankStatus); + + CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); + exception = ex; + } + + await Task.Delay(retryPolicy.GetDelayTimeBeforeNextRetry(retryPolicyContext), cancellationToken).ConfigureAwait(false); + } while ((retryPolicy.ShouldRetry(retryPolicyContext) & RetryCondition.NoRetry) != RetryCondition.NoRetry); + + if (exception != null) + { + CommonLog.LogException(exception, exception.ErrorCode, exception.ErrorMessage); + throw new ClientException(exception.ErrorCode, exception.ErrorMessage); + } + + return null; + } + + public virtual Task GetResponseAsync(HttpRequest httpRequest, CancellationToken cancellationToken) + { + return HttpResponse.GetResponseAsync(httpRequest, cancellationToken); + } + } +} diff --git a/aliyun-net-sdk-core/DefaultAcsClient.cs b/aliyun-net-sdk-core/DefaultAcsClient.cs index 6ccbd0d7d7..3f06cc36cd 100644 --- a/aliyun-net-sdk-core/DefaultAcsClient.cs +++ b/aliyun-net-sdk-core/DefaultAcsClient.cs @@ -40,7 +40,7 @@ namespace Aliyun.Acs.Core { - public class DefaultAcsClient : IAcsClient + public partial class DefaultAcsClient : IAcsClient { private static readonly HttpWebProxy WebProxy = new HttpWebProxy(); private readonly IClientProfile clientProfile; diff --git a/aliyun-net-sdk-core/Http/HttpResponse.Async.cs b/aliyun-net-sdk-core/Http/HttpResponse.Async.cs new file mode 100644 index 0000000000..a85cc4facd --- /dev/null +++ b/aliyun-net-sdk-core/Http/HttpResponse.Async.cs @@ -0,0 +1,218 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Exceptions; +using Aliyun.Acs.Core.Utils; + +namespace Aliyun.Acs.Core.Http +{ + public partial class HttpResponse + { + private static async Task ParseHttpResponseAsync(HttpResponse httpResponse, HttpWebResponse httpWebResponse, CancellationToken cancellationToken) + { + httpResponse.Content = await ReadContentAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); + httpResponse.Status = (int)httpWebResponse.StatusCode; + httpResponse.Headers = new Dictionary(); + httpResponse.Method = ParameterHelper.StringToMethodType(httpWebResponse.Method); + httpResponse.HttpVersion = httpWebResponse.ProtocolVersion.ToString(); + + foreach (var key in httpWebResponse.Headers.AllKeys) + { + httpResponse.Headers.Add(key, httpWebResponse.Headers[key]); + } + + var contentType = DictionaryUtil.Get(httpResponse.Headers, "Content-Type"); + + if (null != contentType) + { + httpResponse.Encoding = "UTF-8"; + var split = contentType.Split(';'); + httpResponse.ContentType = ParameterHelper.StingToFormatType(split[0].Trim()); + if (split.Length > 1 && split[1].Contains("=")) + { + var codings = split[1].Split('='); + httpResponse.Encoding = codings[1].Trim().ToUpper(); + } + } + } + + public static async Task ReadContentAsync(HttpResponse response, HttpWebResponse rsp, CancellationToken cancellationToken) + { + using (var ms = new MemoryStream()) + using (var stream = rsp.GetResponseStream()) + { + if (stream == null) + { + return new byte[0]; + } + + await stream.CopyToAsync(ms, bufferLength, cancellationToken).ConfigureAwait(false); + + return ms.ToArray(); + } + } + + public static async Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken = default(CancellationToken), int? timeout = null) + { + var result = await GetWebRequestAsync(request, timeout, cancellationToken).ConfigureAwait(false); + + var httpWebRequest = result.Item1; + + HttpWebResponse httpWebResponse; + var httpResponse = new HttpResponse(httpWebRequest.RequestUri.AbsoluteUri); + + try + { + using (httpWebResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync().ConfigureAwait(false)) + { + await ParseHttpResponseAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); + return httpResponse; + } + } + catch (WebException ex) + { + if (ex.Response != null) + { + using (httpWebResponse = ex.Response as HttpWebResponse) + { + await ParseHttpResponseAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); + return httpResponse; + } + } + + if (result.Item2.IsCancellationRequested) + { + throw new ClientException("SDK.WebException", + string.Format("HttpWebRequest timeout, the request url is {0} {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); + } + + throw new ClientException("SDK.WebException", + string.Format("HttpWebRequest WebException occured, the request url is {0} {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); + } + catch (IOException ex) + { + throw new ClientException("SDK.ServerUnreachable:", + string.Format("Server unreachable: connection to url: {0} failed. {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, + ex)); + } + catch (Exception ex) + { + throw new ClientException("SDK.Exception", + string.Format("The request url is {0} {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); + } + finally + { + result.Item2.Dispose(); + } + } + + private static async Task> GetWebRequestAsync(HttpRequest request, int? timeout, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var uri = new Uri(request.Url); + var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri); + + httpWebRequest.Proxy = request.WebProxy; + httpWebRequest.Method = request.Method.ToString(); + httpWebRequest.KeepAlive = true; + + httpWebRequest.Timeout = timeout ?? (request.ConnectTimeout > 0 + ? request.ConnectTimeout + : DEFAULT_CONNECT_TIMEOUT_In_MilliSeconds); + + httpWebRequest.ReadWriteTimeout = + request.ReadTimeout > 0 ? request.ReadTimeout : DEFAULT_READ_TIMEOUT_IN_MilliSeconds; + + if (request.IgnoreCertificate) + { + httpWebRequest.ServerCertificateValidationCallback = (s, cert, chains, sslPolicyError) => true; + } + + if (DictionaryUtil.Get(request.Headers, "Accept") != null) + { + httpWebRequest.Accept = DictionaryUtil.Pop(request.Headers, "Accept"); + } + + if (DictionaryUtil.Get(request.Headers, "Date") != null) + { + var headerDate = DictionaryUtil.Pop(request.Headers, "Date"); + httpWebRequest.Date = Convert.ToDateTime(headerDate); + } + + foreach (var header in request.Headers) + { + if (header.Key.Equals("Content-Length")) + { + httpWebRequest.ContentLength = long.Parse(header.Value); + continue; + } + + if (header.Key.Equals("Content-Type")) + { + httpWebRequest.ContentType = header.Value; + continue; + } + + if (header.Key.Equals("User-Agent")) + { + httpWebRequest.UserAgent = header.Value; + continue; + } + + httpWebRequest.Headers.Add(header.Key, header.Value); + } + + var cts = cancellationToken.CanBeCanceled ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken) : new CancellationTokenSource(); + + cts.CancelAfter(timeout > 0 ? timeout.Value : Math.Max(httpWebRequest.Timeout, httpWebRequest.ReadWriteTimeout)); + + cts.Token.Register(httpWebRequest.Abort); + + if ((request.Method == MethodType.POST || request.Method == MethodType.PUT) && request.Content != null) + { + try + { + using (var stream = await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)) + { + await stream.WriteAsync(request.Content, 0, request.Content.Length, cancellationToken).ConfigureAwait(false); + } + } + catch + { + cts.Dispose(); + + throw; + } + } + + return Tuple.Create(httpWebRequest, cts); + } + } +} diff --git a/aliyun-net-sdk-core/Http/HttpResponse.cs b/aliyun-net-sdk-core/Http/HttpResponse.cs index d6fbb10881..d2f83c7482 100644 --- a/aliyun-net-sdk-core/Http/HttpResponse.cs +++ b/aliyun-net-sdk-core/Http/HttpResponse.cs @@ -27,7 +27,7 @@ namespace Aliyun.Acs.Core.Http { - public class HttpResponse : HttpRequest + public partial class HttpResponse : HttpRequest { // Default read timeout 10s private const int DEFAULT_READ_TIMEOUT_IN_MilliSeconds = 10000; @@ -88,24 +88,14 @@ public static byte[] ReadContent(HttpResponse response, HttpWebResponse rsp) using (var ms = new MemoryStream()) using (var stream = rsp.GetResponseStream()) { + if (stream == null) { - var buffer = new byte[bufferLength]; - while (true) - { - var length = stream.Read(buffer, 0, bufferLength); - if (length == 0) - { - break; - } + return new byte[0]; + } - ms.Write(buffer, 0, length); - } + stream.CopyTo(ms, bufferLength); - ms.Seek(0, SeekOrigin.Begin); - var bytes = new byte[ms.Length]; - ms.Read(bytes, 0, bytes.Length); - return bytes; - } + return ms.ToArray(); } } diff --git a/aliyun-net-sdk-core/IAcsClient.Async.cs b/aliyun-net-sdk-core/IAcsClient.Async.cs new file mode 100644 index 0000000000..1506fea787 --- /dev/null +++ b/aliyun-net-sdk-core/IAcsClient.Async.cs @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Auth; +using Aliyun.Acs.Core.Http; +using Aliyun.Acs.Core.Profile; +using Aliyun.Acs.Core.Regions; + +namespace Aliyun.Acs.Core +{ + public partial interface IAcsClient + { + Task GetAcsResponseAsync(AcsRequest request, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetAcsResponseAsync(AcsRequest request, + bool autoRetry, + int maxRetryCounts, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetAcsResponseAsync(AcsRequest request, + IClientProfile profile, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetAcsResponseAsync(AcsRequest request, + string regionId, + Credential credential, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetCommonResponseAsync(CommonRequest request, + CancellationToken cancellationToken = default(CancellationToken)); + + Task DoActionAsync(AcsRequest request, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + bool autoRetry, + int maxRetryCounts, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + IClientProfile profile, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + string regionId, + Credential credential, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + bool autoRetry, + int maxRetryCounts, + IClientProfile profile, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + bool autoRetry, int maxRetryNumber, + string regionId, Credential credential, + Signer signer, FormatType? format, + List endpoints, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + } +} diff --git a/aliyun-net-sdk-core/IAcsClient.cs b/aliyun-net-sdk-core/IAcsClient.cs index 4ea63403dc..ac718c9ef6 100644 --- a/aliyun-net-sdk-core/IAcsClient.cs +++ b/aliyun-net-sdk-core/IAcsClient.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -26,7 +26,7 @@ namespace Aliyun.Acs.Core { - public interface IAcsClient + public partial interface IAcsClient { T GetAcsResponse(AcsRequest request) where T : AcsResponse; diff --git a/aliyun-net-sdk-core/Profile/DefaultProfile.cs b/aliyun-net-sdk-core/Profile/DefaultProfile.cs index e3a6fbfdf6..6946dab01c 100644 --- a/aliyun-net-sdk-core/Profile/DefaultProfile.cs +++ b/aliyun-net-sdk-core/Profile/DefaultProfile.cs @@ -19,7 +19,8 @@ using System; using System.Collections.Generic; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Regions; @@ -100,11 +101,21 @@ public List GetEndpoints(string product, string regionId, string servi return endpointResolve.Resolve(product, regionId, serviceCode, endpointType, _credential, locationConfig); } + public async Task> GetEndpointsAsync(string product, string regionId, string serviceCode, string endpointType, CancellationToken cancellationToken = default(CancellationToken)) + { + return await endpointResolve.ResolveAsync(product, regionId, serviceCode, endpointType, _credential, locationConfig, cancellationToken).ConfigureAwait(false); + } + public List GetEndpoints(string regionId, string product) { return endpointResolve.GetEndpoints(regionId, product); } + public Task> GetEndpointsAsync(string regionId, string product, CancellationToken cancellationToken = default(CancellationToken)) + { + return endpointResolve.GetEndpointsAsync(regionId, product, cancellationToken); + } + public void AddEndpoint(string endpointName, string regionId, string product, string domain, bool isNeverExpire = false) { @@ -112,6 +123,14 @@ public void AddEndpoint(string endpointName, string regionId, string product, st endpointResolve.AddEndpoint(endpointName, regionId, product, domain, isNeverExpire); } + public Task AddEndpointAsync(string endpointName, string regionId, string product, string domain, + bool isNeverExpire = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + EndpointUserConfig.AddEndpoint(product, regionId, domain); + return endpointResolve.AddEndpointAsync(endpointName, regionId, product, domain, isNeverExpire, cancellationToken); + } + public void SetCredentialsProvider(AlibabaCloudCredentialsProvider credentialsProvider) { if (_credential != null) diff --git a/aliyun-net-sdk-core/Profile/IClientProfile.cs b/aliyun-net-sdk-core/Profile/IClientProfile.cs index edee601ee9..e2579bf1f3 100644 --- a/aliyun-net-sdk-core/Profile/IClientProfile.cs +++ b/aliyun-net-sdk-core/Profile/IClientProfile.cs @@ -18,7 +18,8 @@ */ using System.Collections.Generic; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Regions; @@ -38,6 +39,8 @@ public interface IClientProfile List GetEndpoints(string product, string regionId, string serviceCode, string endpointType); + Task> GetEndpointsAsync(string product, string regionId, string serviceCode, string endpointType, CancellationToken cancellationToken = default(CancellationToken)); + void SetLocationConfig(string regionId, string product, string endpoint); void SetCredentialsProvider(AlibabaCloudCredentialsProvider credentialsProvider); @@ -45,5 +48,9 @@ public interface IClientProfile void AddEndpoint(string endpointName, string regionId, string product, string domain, bool isNeverExpire = false); + Task AddEndpointAsync(string endpointName, string regionId, string product, string domain, + bool isNeverExpire = false, + CancellationToken cancellationToken = default(CancellationToken)); + } } diff --git a/aliyun-net-sdk-core/Regions/DescribeEndpointService.cs b/aliyun-net-sdk-core/Regions/DescribeEndpointService.cs index cfcea8d6b9..17f99fc9c2 100644 --- a/aliyun-net-sdk-core/Regions/DescribeEndpointService.cs +++ b/aliyun-net-sdk-core/Regions/DescribeEndpointService.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,6 +17,8 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Regions.Location; using Aliyun.Acs.Core.Regions.Location.Model; @@ -28,5 +30,10 @@ internal interface DescribeEndpointService DescribeEndpointResponse DescribeEndpoint(string regionId, string serviceCode, string endpointType, Credential credential, LocationConfig locationConfig); + + Task DescribeEndpointAsync(string regionId, string serviceCode, string endpointType, + Credential credential, + LocationConfig locationConfig, + CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/aliyun-net-sdk-core/Regions/DescribeEndpointServiceImpl.cs b/aliyun-net-sdk-core/Regions/DescribeEndpointServiceImpl.cs index fa4e7363f3..8b7cad997d 100644 --- a/aliyun-net-sdk-core/Regions/DescribeEndpointServiceImpl.cs +++ b/aliyun-net-sdk-core/Regions/DescribeEndpointServiceImpl.cs @@ -20,7 +20,8 @@ using System; using System.Runtime.CompilerServices; using System.Text; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Reader; @@ -87,6 +88,59 @@ public DescribeEndpointResponse DescribeEndpoint(string regionId, string service return null; } + public async Task DescribeEndpointAsync(string regionId, string serviceCode, string endpointType, + Credential credential, LocationConfig locationConfig, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (string.IsNullOrEmpty(serviceCode)) + { + return null; + } + + if (string.IsNullOrEmpty(endpointType)) + { + endpointType = DEFAULT_ENDPOINT_TYPE; + } + + var request = new DescribeEndpointRequest + { + AcceptFormat = FormatType.JSON, + Id = regionId, + RegionId = locationConfig.RegionId, + LocationProduct = serviceCode, + SecurityToken = credential.SecurityToken, + EndpointType = endpointType + }; + + var signer = Signer.GetSigner(new LegacyCredentials(credential)); + var domain = new ProductDomain(locationConfig.Product, locationConfig.Endpoint); + + var httpRequest = request.SignRequest(signer, credential, FormatType.JSON, domain); + httpRequest.SetConnectTimeoutInMilliSeconds(100000); + httpRequest.SetReadTimeoutInMilliSeconds(100000); + var httpResponse = await GetResponseAsync(httpRequest, cancellationToken).ConfigureAwait(false); + + if (httpResponse.isSuccess()) + { + var data = Encoding.UTF8.GetString(httpResponse.Content); + var response = GetEndpointResponse(data, endpointType); + if (response == null || string.IsNullOrEmpty(response.Endpoint)) + { + return null; + } + + return response; + } + + var error = ReadError(httpResponse, FormatType.JSON); + if (500 <= httpResponse.Status) + { + return null; + } + + return null; + } + private DescribeEndpointResponse GetEndpointResponse(string data, string endpointType) { var reader = ReaderFactory.CreateInstance(FormatType.JSON); @@ -144,5 +198,10 @@ public virtual HttpResponse GetResponse(HttpRequest httpRequest) { return HttpResponse.GetResponse(httpRequest); } + + public virtual Task GetResponseAsync(HttpRequest httpRequest, CancellationToken cancellationToken) + { + return HttpResponse.GetResponseAsync(httpRequest, cancellationToken); + } } } diff --git a/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs b/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs new file mode 100644 index 0000000000..4c07fc0736 --- /dev/null +++ b/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Auth; +using Aliyun.Acs.Core.Exceptions; +using Aliyun.Acs.Core.Regions.Location; +using Aliyun.Acs.Core.Utils; + +namespace Aliyun.Acs.Core.Regions.Endpoints +{ + internal partial class EndpointResolve + { + public async Task> ResolveAsync(string product, string regionId, string serviceCode, string endpointType, + Credential credential, LocationConfig locationConfig, CancellationToken cancellationToken) + { + try + { + if (product == null) + { + return _endpoints; + } + + if (_endpoints.FirstOrDefault(x => x.Name == product) != null) + { + var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); + + if (serviceCode != null && endpoint == null) + { + endpoint = await remoteEndpointProvider.GetEndpointAsync(regionId, product, serviceCode, endpointType, + credential, locationConfig, cancellationToken).ConfigureAwait(false); + } + + if (endpoint != null) + { + foreach (var region in endpoint.RegionIds) + { + foreach (var productDomain in endpoint.ProductDomains.ToList()) + { + AddEndpoint(endpoint.Name, region, product, productDomain.DomainName); + CacheTimeHelper.AddLastClearTimePerProduct(product, region, DateTime.UtcNow); + } + } + } + else + { + throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access."); + } + } + else if (Endpoint.FindProductDomain(regionId, product, _endpoints) == null || + CacheTimeHelper.CheckCacheIsExpire(product, regionId)) + { + var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); + + if (serviceCode != null && endpoint == null) + { + endpoint = await remoteEndpointProvider.GetEndpointAsync(regionId, product, serviceCode, endpointType, + credential, locationConfig, cancellationToken).ConfigureAwait(false); + } + + if (endpoint != null) + { + foreach (var region in endpoint.RegionIds) + { + foreach (var productDomain in endpoint.ProductDomains.ToList()) + { + AddEndpoint(endpoint.Name, region, product, productDomain.DomainName); + CacheTimeHelper.AddLastClearTimePerProduct(product, region, DateTime.UtcNow); + } + } + } + } + } + catch (ClientException ex) + { + CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); + throw new ClientException(ex.ErrorCode, ex.ErrorMessage); + } + + return _endpoints; + } + + public async Task AddEndpointAsync(string endpointName, string regionId, string product, string domain, + bool isNeverExpire = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (0 == _endpoints.Count) + { + _endpoints = await GetEndpointsAsync(regionId, product, cancellationToken).ConfigureAwait(false); + } + + var endpoint = FindEndpointByRegionId(regionId); + if (null == endpoint) + { + var regions = new HashSet { regionId }; + + var productDomains = new List { new ProductDomain(product, domain) }; + endpoint = new Endpoint(endpointName, regions, productDomains); + if (_endpoints == null) + { + _endpoints = new List(); + } + + _endpoints.Add(endpoint); + } + else + { + UpdateEndpoint(regionId, product, domain, endpoint); + } + + if (isNeverExpire) + { + var date = DateTime.UtcNow.AddYears(100); + CacheTimeHelper.AddLastClearTimePerProduct(product, regionId, date); + } + } + + public async Task> GetEndpointsAsync(string regionId, string product, CancellationToken cancellationToken) + { + if (null == _endpoints) + { + var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); + if (endpoint != null) + { + _endpoints = new List { endpoint }; + } + } + + return _endpoints; + } + } +} diff --git a/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs b/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs index ebcf62375a..e6dd313da5 100644 --- a/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs +++ b/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs @@ -1,16 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; - using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Exceptions; -using Aliyun.Acs.Core.Profile; using Aliyun.Acs.Core.Regions.Location; using Aliyun.Acs.Core.Utils; namespace Aliyun.Acs.Core.Regions.Endpoints { - internal class EndpointResolve + internal partial class EndpointResolve { private static List _endpoints; private readonly IEndpointsProvider internalEndpointProvider; diff --git a/aliyun-net-sdk-core/Regions/IEndpointsProvider.cs b/aliyun-net-sdk-core/Regions/IEndpointsProvider.cs index c550c16608..71ea6c0b43 100644 --- a/aliyun-net-sdk-core/Regions/IEndpointsProvider.cs +++ b/aliyun-net-sdk-core/Regions/IEndpointsProvider.cs @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,6 +17,8 @@ * under the License. */ +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Regions.Location; @@ -29,5 +31,13 @@ internal interface IEndpointsProvider Endpoint GetEndpoint(string region, string product, string serviceCode, string endpointType, Credential credential, LocationConfig locationConfig); + + Task GetEndpointAsync(string region, string product, + CancellationToken cancellationToken = default(CancellationToken)); + + Task GetEndpointAsync(string region, string product, string serviceCode, string endpointType, + Credential credential, + LocationConfig locationConfig, + CancellationToken cancellationToken = default(CancellationToken)); } } diff --git a/aliyun-net-sdk-core/Regions/InternalEndpointsParser.cs b/aliyun-net-sdk-core/Regions/InternalEndpointsParser.cs index dc60866f39..a07c2ec0f6 100644 --- a/aliyun-net-sdk-core/Regions/InternalEndpointsParser.cs +++ b/aliyun-net-sdk-core/Regions/InternalEndpointsParser.cs @@ -19,11 +19,9 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Reflection; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; -using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Regions.Location; namespace Aliyun.Acs.Core.Regions @@ -68,6 +66,16 @@ public Endpoint GetEndpoint(string region, string product, string serviceCode, s throw new NotSupportedException(); } + public Task GetEndpointAsync(string region, string product, CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.FromResult(GetEndpoint(region, product)); + } + + public Task GetEndpointAsync(string region, string product, string serviceCode, string endpointType, Credential credential, LocationConfig locationConfig, CancellationToken cancellationToken = default(CancellationToken)) + { + throw new NotSupportedException(); + } + internal class Product { public string Code { get; set; } diff --git a/aliyun-net-sdk-core/Regions/RemoteEndpointsParser.cs b/aliyun-net-sdk-core/Regions/RemoteEndpointsParser.cs index 46e3a73a48..77a9472cbb 100644 --- a/aliyun-net-sdk-core/Regions/RemoteEndpointsParser.cs +++ b/aliyun-net-sdk-core/Regions/RemoteEndpointsParser.cs @@ -19,7 +19,8 @@ using System; using System.Collections.Generic; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Regions.Location; @@ -47,12 +48,39 @@ public Endpoint GetEndpoint(string regionId, string product, string serviceCode, return null; } - Endpoint endpoint = null; - var response = describeEndpointService.DescribeEndpoint(regionId, serviceCode, endpointType, credential, locationConfig); if (response == null) { - return endpoint; + return null; + } + + ISet regionIds = new HashSet(); + regionIds.Add(regionId); + + var productDomainList = new List(); + productDomainList.Add(new ProductDomain(product, response.Endpoint)); + + return new Endpoint(response.RegionId, regionIds, productDomainList); + } + + public Task GetEndpointAsync(string region, string product, CancellationToken cancellationToken = default(CancellationToken)) + { + throw new NotSupportedException(); + } + + public async Task GetEndpointAsync(string regionId, string product, string serviceCode, string endpointType, + Credential credential, LocationConfig locationConfig, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (serviceCode == null) + { + return null; + } + + var response = await describeEndpointService.DescribeEndpointAsync(regionId, serviceCode, endpointType, credential, locationConfig, cancellationToken).ConfigureAwait(false); + if (response == null) + { + return null; } ISet regionIds = new HashSet(); @@ -61,8 +89,7 @@ public Endpoint GetEndpoint(string regionId, string product, string serviceCode, var productDomainList = new List(); productDomainList.Add(new ProductDomain(product, response.Endpoint)); - endpoint = new Endpoint(response.RegionId, regionIds, productDomainList); - return endpoint; + return new Endpoint(response.RegionId, regionIds, productDomainList); } } } diff --git a/aliyun-net-sdk-core/aliyun-net-sdk-core.vs2017.csproj b/aliyun-net-sdk-core/aliyun-net-sdk-core.vs2017.csproj index 49b585fd2a..1511d4bdee 100644 --- a/aliyun-net-sdk-core/aliyun-net-sdk-core.vs2017.csproj +++ b/aliyun-net-sdk-core/aliyun-net-sdk-core.vs2017.csproj @@ -15,7 +15,7 @@ aliyun-net-sdk-core false - 4 + 6 @@ -42,19 +42,16 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers - - - - \ No newline at end of file diff --git a/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs b/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs new file mode 100644 index 0000000000..62fa159fcc --- /dev/null +++ b/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Exceptions; +using Aliyun.Acs.Core.Http; +using Aliyun.Acs.Vpc.Model.V20160428; + +using Xunit; + +namespace Aliyun.Acs.Feature.Test.Timeout +{ + [Trait("Category", "FeatureTest")] + public class AsyncTimeoutTest + { + [Fact] + public async Task TestConnectTimeoutWithException() + { + var request = new HttpRequest("https://alibaba.great"); + request.Method = MethodType.GET; + request.SetConnectTimeoutInMilliSeconds(1); + + var exception = await Assert.ThrowsAsync(() => HttpResponse.GetResponseAsync(request)); + + Assert.NotNull(exception.Message); + + request = new HttpRequest("https://alibaba.great"); + request.Method = MethodType.GET; + + using (var cts = new CancellationTokenSource(10)) + { + exception = await Assert.ThrowsAsync(() => HttpResponse.GetResponseAsync(request, cts.Token)); + + Assert.NotNull(exception.Message); + } + } + + [Fact] + public async Task TestVPCConnectTimeoutWithException() + { + var request = new DescribeAccessPointsRequest(); + request.SetConnectTimeoutInMilliSeconds(1); + + Exception exception = await Assert.ThrowsAsync(() => FeatureTest.DefaultClient.GetAcsResponseAsync(request)); + + Assert.NotNull(exception.Message); + + request = new DescribeAccessPointsRequest(); + + using (var cts = new CancellationTokenSource(10)) + { + exception = null; + + try + { + await FeatureTest.DefaultClient.GetAcsResponseAsync(request, cts.Token); + } + catch (Exception e) + { + exception = e; + } + + Assert.NotNull(exception); + Assert.NotNull(exception.Message); + } + } + } +} From 471ceb22fad84cc2a0a41f40299fef6959faf733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 11:48:22 +0800 Subject: [PATCH 2/8] pass cancellationToken --- .../Auth/Provider/DefaultCredentialProvider.Async.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs index 13edc850ee..f374a1e1ea 100644 --- a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs +++ b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs @@ -97,7 +97,7 @@ await GetCredentialFileAlibabaCloudCredentialAsync(cancellationToken).ConfigureA accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); regionId = iniReader.GetValue("region_id", userDefineSectionNode); - return await GetAccessKeyCredentialAsync().ConfigureAwait(false); + return await GetAccessKeyCredentialAsync(cancellationToken).ConfigureAwait(false); } if (iniKeyTypeValue.Equals("ecs_ram_role")) @@ -114,7 +114,7 @@ await GetCredentialFileAlibabaCloudCredentialAsync(cancellationToken).ConfigureA accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); roleArn = iniReader.GetValue("role_arn", userDefineSectionNode); - return await GetRamRoleArnAlibabaCloudCredentialAsync().ConfigureAwait(false); + return await GetRamRoleArnAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); } if (iniKeyTypeValue.Equals("rsa_key_pair")) @@ -122,7 +122,7 @@ await GetCredentialFileAlibabaCloudCredentialAsync(cancellationToken).ConfigureA publicKeyId = iniReader.GetValue("public_key_id", userDefineSectionNode); privateKeyFile = iniReader.GetValue("private_key_file", userDefineSectionNode); - return await GetRsaKeyPairAlibabaCloudCredentialAsync().ConfigureAwait(false); + return await GetRsaKeyPairAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); } } else From 39775d32d0783674bd64387ffc1a3eb9ee160567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 11:51:46 +0800 Subject: [PATCH 3/8] revert --- aliyun-net-sdk-core/AcsRequest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aliyun-net-sdk-core/AcsRequest.cs b/aliyun-net-sdk-core/AcsRequest.cs index 2c32a2e118..d98444b818 100644 --- a/aliyun-net-sdk-core/AcsRequest.cs +++ b/aliyun-net-sdk-core/AcsRequest.cs @@ -21,7 +21,7 @@ using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; + using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Regions; @@ -77,7 +77,7 @@ public virtual string RegionId throw new ArgumentException("regionId is invalid", "regionId"); } } - + regionId = value; } } @@ -103,7 +103,7 @@ public string ProductNetwork throw new ArgumentException("productNetwork is invalid", "productNetwork"); } } - + productNetwork = value; } } @@ -124,7 +124,7 @@ public string ProductSuffix throw new ArgumentException("productSuffix is invalid", "productSuffix"); } } - + productSuffix = value; } } From 1213a4420e9ae7b30bbeb3039b5adac9656b2b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 11:54:24 +0800 Subject: [PATCH 4/8] Revert "fixed region regex" This reverts commit e22e6d54da80945d42da120c19aa1bd7bf1c9e4d. # Conflicts: # aliyun-net-sdk-core/AcsRequest.cs --- aliyun-net-sdk-core/AcsRequest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aliyun-net-sdk-core/AcsRequest.cs b/aliyun-net-sdk-core/AcsRequest.cs index d98444b818..4ecfffb38c 100644 --- a/aliyun-net-sdk-core/AcsRequest.cs +++ b/aliyun-net-sdk-core/AcsRequest.cs @@ -77,7 +77,7 @@ public virtual string RegionId throw new ArgumentException("regionId is invalid", "regionId"); } } - + regionId = value; } } @@ -103,7 +103,7 @@ public string ProductNetwork throw new ArgumentException("productNetwork is invalid", "productNetwork"); } } - + productNetwork = value; } } @@ -124,7 +124,7 @@ public string ProductSuffix throw new ArgumentException("productSuffix is invalid", "productSuffix"); } } - + productSuffix = value; } } From 0f2bb52e538f054f43d8501b989728c66de4ffb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 14:08:33 +0800 Subject: [PATCH 5/8] Codacy/PR Quality Review --- .../DefaultCredentialProvider.Async.cs | 243 ----------------- .../Provider/DefaultCredentialProvider.cs | 220 ++++++++++++++- ...MetadataServiceCredentialsFetcher.Async.cs | 130 --------- .../ECSMetadataServiceCredentialsFetcher.cs | 100 ++++++- aliyun-net-sdk-core/DefaultAcsClient.Async.cs | 257 ------------------ aliyun-net-sdk-core/DefaultAcsClient.cs | 227 +++++++++++++++- .../Http/HttpResponse.Async.cs | 218 --------------- aliyun-net-sdk-core/Http/HttpResponse.cs | 193 ++++++++++++- aliyun-net-sdk-core/IAcsClient.Async.cs | 92 ------- aliyun-net-sdk-core/IAcsClient.cs | 70 ++++- aliyun-net-sdk-core/Profile/DefaultProfile.cs | 8 +- aliyun-net-sdk-core/Profile/IClientProfile.cs | 4 +- .../Endpoints/EndpointResolve.Async.cs | 133 --------- .../Regions/Endpoints/EndpointResolve.cs | 125 ++++++++- 14 files changed, 929 insertions(+), 1091 deletions(-) delete mode 100644 aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs delete mode 100644 aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs delete mode 100644 aliyun-net-sdk-core/DefaultAcsClient.Async.cs delete mode 100644 aliyun-net-sdk-core/Http/HttpResponse.Async.cs delete mode 100644 aliyun-net-sdk-core/IAcsClient.Async.cs delete mode 100644 aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs diff --git a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs deleted file mode 100644 index f374a1e1ea..0000000000 --- a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.Async.cs +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Aliyun.Acs.Core.Exceptions; -using Aliyun.Acs.Core.Profile; -using Aliyun.Acs.Core.Utils; - -namespace Aliyun.Acs.Core.Auth.Provider -{ - public partial class DefaultCredentialProvider - { - public async Task GetAlibabaCloudClientCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - var credential = await GetEnvironmentAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false) ?? - await GetCredentialFileAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false) ?? - await GetInstanceRamRoleAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); - - if (credential == null) - { - throw new ClientException("There is no credential chain can use."); - } - - return credential; - } - - public async Task GetEnvironmentAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - if (null == accessKeyId || null == accessKeySecret) - { - return null; - } - - if (accessKeyId.Equals("") || accessKeySecret.Equals("")) - { - throw new ClientException( - "Environment credential variable 'ALIBABA_CLOUD_ACCESS_KEY_*' cannot be empty"); - } - - return defaultProfile.DefaultClientName.Equals("default") ? await GetAccessKeyCredentialAsync(cancellationToken).ConfigureAwait(false) : null; - } - - public async Task GetCredentialFileAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - if (null == credentialFileLocation) - { - credentialFileLocation = GetHomePath(); - var slash = EnvironmentUtil.GetOSSlash(); - var fileLocation = EnvironmentUtil.GetComposedPath(credentialFileLocation, slash); - - if (File.Exists(fileLocation)) - { - credentialFileLocation = fileLocation; - } - else - { - return null; - } - } - - if (credentialFileLocation.Equals("")) - { - throw new ClientException( - "Credentials file environment variable 'ALIBABA_CLOUD_CREDENTIALS_FILE' cannot be empty"); - } - - var iniReader = new IniReader(credentialFileLocation); - var sectionNameList = iniReader.GetSections(); - - if (null != defaultProfile.DefaultClientName) - { - var userDefineSectionNode = defaultProfile.DefaultClientName; - - var iniKeyTypeValue = iniReader.GetValue("type", userDefineSectionNode); - - if (iniKeyTypeValue.Equals("access_key")) - { - accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); - accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); - regionId = iniReader.GetValue("region_id", userDefineSectionNode); - - return await GetAccessKeyCredentialAsync(cancellationToken).ConfigureAwait(false); - } - - if (iniKeyTypeValue.Equals("ecs_ram_role")) - { - roleName = iniReader.GetValue("role_name", userDefineSectionNode); - regionId = iniReader.GetValue("region_id", userDefineSectionNode); - - return await GetInstanceRamRoleAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); - } - - if (iniKeyTypeValue.Equals("ram_role_arn")) - { - accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); - accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); - roleArn = iniReader.GetValue("role_arn", userDefineSectionNode); - - return await GetRamRoleArnAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); - } - - if (iniKeyTypeValue.Equals("rsa_key_pair")) - { - publicKeyId = iniReader.GetValue("public_key_id", userDefineSectionNode); - privateKeyFile = iniReader.GetValue("private_key_file", userDefineSectionNode); - - return await GetRsaKeyPairAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); - } - } - else - { - foreach (var sectionItem in sectionNameList) - { - if (!sectionItem.Equals("default")) - { - continue; - } - - accessKeyId = iniReader.GetValue("access_key_id", "default"); - accessKeySecret = iniReader.GetValue("access_key_secret", "default"); - regionId = iniReader.GetValue("region_id", "default"); - - return await GetAccessKeyCredentialAsync().ConfigureAwait(false); - } - } - - return null; - } - - public virtual Task GetInstanceRamRoleAlibabaCloudCredentialAsync(CancellationToken cancellationToken) - { - if (null == regionId || regionId.Equals("")) - { - throw new ClientException("RegionID cannot be null or empty."); - } - - if (!defaultProfile.DefaultClientName.Equals("default")) - { - return null; - } - - InstanceProfileCredentialsProvider instanceProfileCredentialProvider; - if (null != alibabaCloudCredentialProvider) - { - instanceProfileCredentialProvider = - (InstanceProfileCredentialsProvider)alibabaCloudCredentialProvider; - } - else - { - instanceProfileCredentialProvider = new InstanceProfileCredentialsProvider(roleName); - } - - return instanceProfileCredentialProvider.GetCredentialsAsync(cancellationToken); - } - - public Task GetAccessKeyCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || - string.IsNullOrEmpty(regionId)) - { - throw new ClientException("Missing required variable option for 'default Client'"); - } - - var accessKeyCredentialProvider = - new AccessKeyCredentialProvider(accessKeyId, accessKeySecret); - - return accessKeyCredentialProvider.GetCredentialsAsync(cancellationToken); - } - - public virtual Task GetRamRoleArnAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || - string.IsNullOrEmpty(regionId)) - { - throw new ClientException("Missing required variable option for 'default Client'"); - } - - var credential = new BasicSessionCredentials(accessKeyId, accessKeySecret, - STSAssumeRoleSessionCredentialsProvider.GetNewRoleSessionName(), - 3600 - ); - var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); - - STSAssumeRoleSessionCredentialsProvider stsAsssumeRoleSessionCredentialProvider; - - if (null != alibabaCloudCredentialProvider) - { - stsAsssumeRoleSessionCredentialProvider = - (STSAssumeRoleSessionCredentialsProvider)alibabaCloudCredentialProvider; - } - else - { - stsAsssumeRoleSessionCredentialProvider = - new STSAssumeRoleSessionCredentialsProvider(credential, roleArn, profile); - } - - return stsAsssumeRoleSessionCredentialProvider.GetCredentialsAsync(cancellationToken); - } - - public virtual Task GetRsaKeyPairAlibabaCloudCredentialAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - if (string.IsNullOrEmpty(publicKeyId) || string.IsNullOrEmpty(privateKeyFile) || - string.IsNullOrEmpty(regionId)) - { - throw new ClientException("Missing required variable option for 'default Client'"); - } - - var rsaKeyPairCredential = new KeyPairCredentials(publicKeyId, privateKeyFile); - var profile = DefaultProfile.GetProfile(regionId, publicKeyId, privateKeyFile); - - RsaKeyPairCredentialProvider rsaKeyPairCredentialProvider; - - if (null != alibabaCloudCredentialProvider) - { - rsaKeyPairCredentialProvider = (RsaKeyPairCredentialProvider)alibabaCloudCredentialProvider; - } - else - { - rsaKeyPairCredentialProvider = new RsaKeyPairCredentialProvider(rsaKeyPairCredential, profile); - } - - return rsaKeyPairCredentialProvider.GetCredentialsAsync(cancellationToken); - } - } -} diff --git a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs index 29f4b73143..7b6e77154d 100644 --- a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs @@ -18,14 +18,15 @@ */ using System.IO; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Profile; using Aliyun.Acs.Core.Utils; namespace Aliyun.Acs.Core.Auth.Provider { - public partial class DefaultCredentialProvider + public class DefaultCredentialProvider { private static IClientProfile defaultProfile; @@ -288,5 +289,220 @@ public virtual string GetHomePath() { return EnvironmentUtil.GetHomePath(); } + + #region Async + + public async Task GetAlibabaCloudClientCredentialAsync(CancellationToken cancellationToken) + { + var credential = await GetEnvironmentAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false) ?? + await GetCredentialFileAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false) ?? + await GetInstanceRamRoleAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); + + if (credential == null) + { + throw new ClientException("There is no credential chain can use."); + } + + return credential; + } + + public async Task GetEnvironmentAlibabaCloudCredentialAsync(CancellationToken cancellationToken) + { + if (null == accessKeyId || null == accessKeySecret) + { + return null; + } + + if (accessKeyId.Equals("") || accessKeySecret.Equals("")) + { + throw new ClientException( + "Environment credential variable 'ALIBABA_CLOUD_ACCESS_KEY_*' cannot be empty"); + } + + return defaultProfile.DefaultClientName.Equals("default") ? await GetAccessKeyCredentialAsync(cancellationToken).ConfigureAwait(false) : null; + } + + public async Task GetCredentialFileAlibabaCloudCredentialAsync(CancellationToken cancellationToken) + { + if (null == credentialFileLocation) + { + credentialFileLocation = GetHomePath(); + var slash = EnvironmentUtil.GetOSSlash(); + var fileLocation = EnvironmentUtil.GetComposedPath(credentialFileLocation, slash); + + if (File.Exists(fileLocation)) + { + credentialFileLocation = fileLocation; + } + else + { + return null; + } + } + + if (credentialFileLocation.Equals("")) + { + throw new ClientException( + "Credentials file environment variable 'ALIBABA_CLOUD_CREDENTIALS_FILE' cannot be empty"); + } + + var iniReader = new IniReader(credentialFileLocation); + var sectionNameList = iniReader.GetSections(); + + if (null != defaultProfile.DefaultClientName) + { + var userDefineSectionNode = defaultProfile.DefaultClientName; + + var iniKeyTypeValue = iniReader.GetValue("type", userDefineSectionNode); + + if (iniKeyTypeValue.Equals("access_key")) + { + accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); + accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); + regionId = iniReader.GetValue("region_id", userDefineSectionNode); + + return await GetAccessKeyCredentialAsync(cancellationToken).ConfigureAwait(false); + } + + if (iniKeyTypeValue.Equals("ecs_ram_role")) + { + roleName = iniReader.GetValue("role_name", userDefineSectionNode); + regionId = iniReader.GetValue("region_id", userDefineSectionNode); + + return await GetInstanceRamRoleAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); + } + + if (iniKeyTypeValue.Equals("ram_role_arn")) + { + accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); + accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); + roleArn = iniReader.GetValue("role_arn", userDefineSectionNode); + + return await GetRamRoleArnAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); + } + + if (iniKeyTypeValue.Equals("rsa_key_pair")) + { + publicKeyId = iniReader.GetValue("public_key_id", userDefineSectionNode); + privateKeyFile = iniReader.GetValue("private_key_file", userDefineSectionNode); + + return await GetRsaKeyPairAlibabaCloudCredentialAsync(cancellationToken).ConfigureAwait(false); + } + } + else + { + foreach (var sectionItem in sectionNameList) + { + if (!sectionItem.Equals("default")) + { + continue; + } + + accessKeyId = iniReader.GetValue("access_key_id", "default"); + accessKeySecret = iniReader.GetValue("access_key_secret", "default"); + regionId = iniReader.GetValue("region_id", "default"); + + return await GetAccessKeyCredentialAsync(cancellationToken).ConfigureAwait(false); + } + } + + return null; + } + + public virtual Task GetInstanceRamRoleAlibabaCloudCredentialAsync(CancellationToken cancellationToken) + { + if (null == regionId || regionId.Equals("")) + { + throw new ClientException("RegionID cannot be null or empty."); + } + + if (!defaultProfile.DefaultClientName.Equals("default")) + { + return null; + } + + InstanceProfileCredentialsProvider instanceProfileCredentialProvider; + if (null != alibabaCloudCredentialProvider) + { + instanceProfileCredentialProvider = + (InstanceProfileCredentialsProvider)alibabaCloudCredentialProvider; + } + else + { + instanceProfileCredentialProvider = new InstanceProfileCredentialsProvider(roleName); + } + + return instanceProfileCredentialProvider.GetCredentialsAsync(cancellationToken); + } + + public Task GetAccessKeyCredentialAsync(CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || + string.IsNullOrEmpty(regionId)) + { + throw new ClientException("Missing required variable option for 'default Client'"); + } + + var accessKeyCredentialProvider = + new AccessKeyCredentialProvider(accessKeyId, accessKeySecret); + + return accessKeyCredentialProvider.GetCredentialsAsync(cancellationToken); + } + + public virtual Task GetRamRoleArnAlibabaCloudCredentialAsync(CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || + string.IsNullOrEmpty(regionId)) + { + throw new ClientException("Missing required variable option for 'default Client'"); + } + + var credential = new BasicSessionCredentials(accessKeyId, accessKeySecret, + STSAssumeRoleSessionCredentialsProvider.GetNewRoleSessionName(), + 3600 + ); + var profile = DefaultProfile.GetProfile(regionId, accessKeyId, accessKeySecret); + + STSAssumeRoleSessionCredentialsProvider stsAsssumeRoleSessionCredentialProvider; + + if (null != alibabaCloudCredentialProvider) + { + stsAsssumeRoleSessionCredentialProvider = + (STSAssumeRoleSessionCredentialsProvider)alibabaCloudCredentialProvider; + } + else + { + stsAsssumeRoleSessionCredentialProvider = + new STSAssumeRoleSessionCredentialsProvider(credential, roleArn, profile); + } + + return stsAsssumeRoleSessionCredentialProvider.GetCredentialsAsync(cancellationToken); + } + + public virtual Task GetRsaKeyPairAlibabaCloudCredentialAsync(CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(publicKeyId) || string.IsNullOrEmpty(privateKeyFile) || + string.IsNullOrEmpty(regionId)) + { + throw new ClientException("Missing required variable option for 'default Client'"); + } + + var rsaKeyPairCredential = new KeyPairCredentials(publicKeyId, privateKeyFile); + var profile = DefaultProfile.GetProfile(regionId, publicKeyId, privateKeyFile); + + RsaKeyPairCredentialProvider rsaKeyPairCredentialProvider; + + if (null != alibabaCloudCredentialProvider) + { + rsaKeyPairCredentialProvider = (RsaKeyPairCredentialProvider)alibabaCloudCredentialProvider; + } + else + { + rsaKeyPairCredentialProvider = new RsaKeyPairCredentialProvider(rsaKeyPairCredential, profile); + } + + return rsaKeyPairCredentialProvider.GetCredentialsAsync(cancellationToken); + } + #endregion } } diff --git a/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs b/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs deleted file mode 100644 index 685fa5c4f9..0000000000 --- a/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.Async.cs +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Aliyun.Acs.Core.Exceptions; -using Aliyun.Acs.Core.Http; -using Aliyun.Acs.Core.Reader; -using Aliyun.Acs.Core.Utils; - -namespace Aliyun.Acs.Core.Auth -{ - public partial class ECSMetadataServiceCredentialsFetcher - { - - public async Task GetCredentialsAsync(CancellationToken cancellationToken) - { - return await FetchAsync(cancellationToken).ConfigureAwait(false); - } - - public async Task GetMetadataAsync(CancellationToken cancellationToken) - { - var request = new HttpRequest(credentialUrl); - request.Method = MethodType.GET; - request.SetConnectTimeoutInMilliSeconds(connectionTimeoutInMilliseconds); - - HttpResponse response; - try - { - response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); - } - catch (WebException e) - { - throw new ClientException("Failed to connect ECS Metadata Service: " + e); - } - - if (response.Status != 200) - { - throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG + " HttpCode=" + response.Status); - } - - return Encoding.UTF8.GetString(response.Content); - } - - public virtual async Task FetchAsync(CancellationToken cancellationToken) - { - Dictionary dic; - try - { - var jsonContent = await GetMetadataAsync(cancellationToken).ConfigureAwait(false); - - IReader reader = new JsonReader(); - dic = reader.Read(jsonContent, ""); - } - catch (Exception e) - { - throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG + " Reason: " + e); - } - - if ( - DictionaryUtil.Get(dic, ".Code") == null || - DictionaryUtil.Get(dic, ".AccessKeyId") == null || - DictionaryUtil.Get(dic, ".AccessKeySecret") == null || - DictionaryUtil.Get(dic, ".SecurityToken") == null || - DictionaryUtil.Get(dic, ".Expiration") == null - ) - { - throw new ClientException("Invalid json got from ECS Metadata service."); - } - - if (!"Success".Equals(DictionaryUtil.Get(dic, ".Code"))) - { - throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG); - } - - return new InstanceProfileCredentials( - DictionaryUtil.Get(dic, ".AccessKeyId"), - DictionaryUtil.Get(dic, ".AccessKeySecret"), - DictionaryUtil.Get(dic, ".SecurityToken"), - DictionaryUtil.Get(dic, ".Expiration"), - DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS - ); - } - - public async Task FetchAsync(int retryTimes, CancellationToken cancellationToken) - { - for (var i = 0; i <= retryTimes; i++) - { - try - { - return await FetchAsync(cancellationToken).ConfigureAwait(false); - } - catch (ClientException e) - { - if (i == retryTimes) - { - throw new ClientException(e.ErrorCode, e.ErrorMessage); - } - } - } - - throw new ClientException("Failed to connect ECS Metadata Service: Max retry times exceeded."); - } - - public virtual Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken) - { - return HttpResponse.GetResponseAsync(request, cancellationToken); - } - } -} diff --git a/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs b/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs index edecf2a2a4..21c24b7de2 100644 --- a/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs +++ b/aliyun-net-sdk-core/Auth/Provider/ECSMetadataServiceCredentialsFetcher.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Net; using System.Text; +using System.Threading; using System.Threading.Tasks; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Http; @@ -29,7 +30,7 @@ namespace Aliyun.Acs.Core.Auth { - public partial class ECSMetadataServiceCredentialsFetcher : AlibabaCloudCredentialsProvider + public class ECSMetadataServiceCredentialsFetcher : AlibabaCloudCredentialsProvider { private const string URL_IN_ECS_METADATA = "/latest/meta-data/ram/security-credentials/"; private const int DEFAULT_TIMEOUT_IN_MILLISECONDS = 5000; @@ -174,5 +175,102 @@ public virtual HttpResponse GetResponse(HttpRequest request) { return HttpResponse.GetResponse(request); } + + #region Async + + public async Task GetCredentialsAsync(CancellationToken cancellationToken) + { + return await FetchAsync(cancellationToken).ConfigureAwait(false); + } + + public async Task GetMetadataAsync(CancellationToken cancellationToken) + { + var request = new HttpRequest(credentialUrl); + request.Method = MethodType.GET; + request.SetConnectTimeoutInMilliSeconds(connectionTimeoutInMilliseconds); + + HttpResponse response; + try + { + response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); + } + catch (WebException e) + { + throw new ClientException("Failed to connect ECS Metadata Service: " + e); + } + + if (response.Status != 200) + { + throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG + " HttpCode=" + response.Status); + } + + return Encoding.UTF8.GetString(response.Content); + } + + public virtual async Task FetchAsync(CancellationToken cancellationToken) + { + Dictionary dic; + try + { + var jsonContent = await GetMetadataAsync(cancellationToken).ConfigureAwait(false); + + IReader reader = new JsonReader(); + dic = reader.Read(jsonContent, ""); + } + catch (Exception e) + { + throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG + " Reason: " + e); + } + + if ( + DictionaryUtil.Get(dic, ".Code") == null || + DictionaryUtil.Get(dic, ".AccessKeyId") == null || + DictionaryUtil.Get(dic, ".AccessKeySecret") == null || + DictionaryUtil.Get(dic, ".SecurityToken") == null || + DictionaryUtil.Get(dic, ".Expiration") == null + ) + { + throw new ClientException("Invalid json got from ECS Metadata service."); + } + + if (!"Success".Equals(DictionaryUtil.Get(dic, ".Code"))) + { + throw new ClientException(ECS_METADAT_FETCH_ERROR_MSG); + } + + return new InstanceProfileCredentials( + DictionaryUtil.Get(dic, ".AccessKeyId"), + DictionaryUtil.Get(dic, ".AccessKeySecret"), + DictionaryUtil.Get(dic, ".SecurityToken"), + DictionaryUtil.Get(dic, ".Expiration"), + DEFAULT_ECS_SESSION_TOKEN_DURATION_SECONDS + ); + } + + public async Task FetchAsync(int retryTimes, CancellationToken cancellationToken) + { + for (var i = 0; i <= retryTimes; i++) + { + try + { + return await FetchAsync(cancellationToken).ConfigureAwait(false); + } + catch (ClientException e) + { + if (i == retryTimes) + { + throw new ClientException(e.ErrorCode, e.ErrorMessage); + } + } + } + + throw new ClientException("Failed to connect ECS Metadata Service: Max retry times exceeded."); + } + + public virtual Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken) + { + return HttpResponse.GetResponseAsync(request, cancellationToken); + } + #endregion } } diff --git a/aliyun-net-sdk-core/DefaultAcsClient.Async.cs b/aliyun-net-sdk-core/DefaultAcsClient.Async.cs deleted file mode 100644 index bc93643b51..0000000000 --- a/aliyun-net-sdk-core/DefaultAcsClient.Async.cs +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Aliyun.Acs.Core.Auth; -using Aliyun.Acs.Core.Auth.Provider; -using Aliyun.Acs.Core.Exceptions; -using Aliyun.Acs.Core.Http; -using Aliyun.Acs.Core.Profile; -using Aliyun.Acs.Core.Regions; -using Aliyun.Acs.Core.Retry; -using Aliyun.Acs.Core.Retry.Condition; -using Aliyun.Acs.Core.Utils; - -namespace Aliyun.Acs.Core -{ - public partial class DefaultAcsClient - { - public async Task GetAcsResponseAsync(AcsRequest request, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse - { - var httpResponse = await DoActionAsync(request, cancellationToken).ConfigureAwait(false); - return ParseAcsResponse(request, httpResponse); - } - - public async Task GetAcsResponseAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse - { - var httpResponse = await DoActionAsync(request, autoRetry, maxRetryNumber, cancellationToken).ConfigureAwait(false); - return ParseAcsResponse(request, httpResponse); - } - - public async Task GetAcsResponseAsync(AcsRequest request, IClientProfile profile, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse - { - var httpResponse = await DoActionAsync(request, profile, cancellationToken).ConfigureAwait(false); - return ParseAcsResponse(request, httpResponse); - } - - public async Task GetAcsResponseAsync(AcsRequest request, string regionId, Credential credential, CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse - { - var httpResponse = await DoActionAsync(request, regionId, credential, cancellationToken).ConfigureAwait(false); - return ParseAcsResponse(request, httpResponse); - } - - public async Task GetCommonResponseAsync(CommonRequest request, CancellationToken cancellationToken = default(CancellationToken)) - { - var httpResponse = await DoActionAsync(request.BuildRequest(), cancellationToken).ConfigureAwait(false); - string data = null; - if (httpResponse.Content != null) - { - data = Encoding.UTF8.GetString(httpResponse.Content); - } - - var response = new CommonResponse - { - Data = data, - HttpResponse = httpResponse, - HttpStatus = httpResponse.Status - }; - - return response; - } - - public Task DoActionAsync(AcsRequest request, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse - { - return DoActionAsync(request, AutoRetry, MaxRetryNumber, clientProfile, cancellationToken); - } - - public Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse - { - return DoActionAsync(request, autoRetry, maxRetryNumber, clientProfile, cancellationToken); - } - - public Task DoActionAsync(AcsRequest request, IClientProfile profile, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse - { - return DoActionAsync(request, AutoRetry, MaxRetryNumber, profile, cancellationToken); - } - - public async Task DoActionAsync(AcsRequest request, string regionId, Credential credential, CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse - { - var signer = Signer.GetSigner(new LegacyCredentials(credential)); - FormatType? format = null; - if (null == request.RegionId) - { - request.RegionId = regionId; - } - - if (request.ProductDomain == null) - { - request.ProductDomain = EndpointUserConfig.GetProductDomain(request.Product, request.RegionId); - if (request.ProductDomain == null) - { - request.SetProductDomain(); - } - } - - List endpoints = null; - if (null != clientProfile) - { - format = clientProfile.GetFormat(); - if (request.ProductDomain == null) - { - endpoints = await clientProfile.GetEndpointsAsync(request.Product, request.RegionId, request.LocationProduct, - request.LocationEndpointType, cancellationToken).ConfigureAwait(false); - } - } - - return await DoActionAsync(request, AutoRetry, MaxRetryNumber, request.RegionId, credential, signer, format, endpoints, cancellationToken).ConfigureAwait(false); - } - - public async Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, IClientProfile profile, CancellationToken cancellationToken) where T : AcsResponse - { - if (null == profile) - { - throw new ClientException("SDK.InvalidProfile", "No active profile found."); - } - - var retry = autoRetry; - var retryNumber = maxRetryNumber; - var region = profile.GetRegionId(); - if (null == request.RegionId) - { - request.RegionId = region; - } - - if (request.ProductDomain == null) - { - request.ProductDomain = EndpointUserConfig.GetProductDomain(request.Product, request.RegionId); - if (request.ProductDomain == null) - { - request.SetProductDomain(); - } - } - - var credentials = await credentialsProvider.GetCredentialsAsync(cancellationToken).ConfigureAwait(false); - if (credentials == null) - { - credentials = await new DefaultCredentialProvider().GetAlibabaCloudClientCredentialAsync(cancellationToken).ConfigureAwait(false); - } - - var signer = Signer.GetSigner(credentials); - var format = profile.GetFormat(); - List endpoints = null; - - if (request.ProductDomain == null) - { - endpoints = await clientProfile.GetEndpointsAsync(request.Product, request.RegionId, - request.LocationProduct, - request.LocationEndpointType, cancellationToken).ConfigureAwait(false); - } - - return await DoActionAsync(request, retry, retryNumber, request.RegionId, credentials, signer, format, endpoints, cancellationToken).ConfigureAwait(false); - } - - public Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, string regionId, - Credential credential, Signer signer, FormatType? format, List endpoints, CancellationToken cancellationToken = default(CancellationToken)) where T : AcsResponse - { - return DoActionAsync(request, autoRetry, maxRetryNumber, regionId, new LegacyCredentials(credential), signer, - format, endpoints, cancellationToken); - } - - public virtual async Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, - string regionId, - AlibabaCloudCredentials credentials, Signer signer, FormatType? format, List endpoints, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse - { - var httpStatusCode = ""; - var retryAttemptTimes = 0; - ClientException exception; - RetryPolicyContext retryPolicyContext; - - do - { - try - { - var watch = Stopwatch.StartNew(); - - FormatType? requestFormatType = request.AcceptFormat; - format = requestFormatType; - - var domain = request.ProductDomain ?? - Endpoint.FindProductDomain(regionId, request.Product, endpoints); - - if (null == domain) - { - throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access."); - } - - var userAgent = UserAgent.Resolve(request.GetSysUserAgentConfig(), userAgentConfig); - DictionaryUtil.Add(request.Headers, "User-Agent", userAgent); - DictionaryUtil.Add(request.Headers, "x-acs-version", request.Version); - if (!string.IsNullOrWhiteSpace(request.ActionName)) - { - DictionaryUtil.Add(request.Headers, "x-acs-action", request.ActionName); - } - var httpRequest = request.SignRequest(signer, credentials, format, domain); - ResolveTimeout(httpRequest, request.Product, request.Version, request.ActionName); - SetHttpsInsecure(IgnoreCertificate); - ResolveProxy(httpRequest, request); - var response = await GetResponseAsync(httpRequest, cancellationToken).ConfigureAwait(false); - - httpStatusCode = response.Status.ToString(); - PrintHttpDebugMsg(request, response); - watch.Stop(); - CommonLog.ExecuteTime = watch.ElapsedMilliseconds; - return response; - } - catch (ClientException ex) - { - retryPolicyContext = new RetryPolicyContext(ex, httpStatusCode, retryAttemptTimes, request.Product, - request.Version, - request.ActionName, RetryCondition.BlankStatus); - - CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); - exception = ex; - } - - await Task.Delay(retryPolicy.GetDelayTimeBeforeNextRetry(retryPolicyContext), cancellationToken).ConfigureAwait(false); - } while ((retryPolicy.ShouldRetry(retryPolicyContext) & RetryCondition.NoRetry) != RetryCondition.NoRetry); - - if (exception != null) - { - CommonLog.LogException(exception, exception.ErrorCode, exception.ErrorMessage); - throw new ClientException(exception.ErrorCode, exception.ErrorMessage); - } - - return null; - } - - public virtual Task GetResponseAsync(HttpRequest httpRequest, CancellationToken cancellationToken) - { - return HttpResponse.GetResponseAsync(httpRequest, cancellationToken); - } - } -} diff --git a/aliyun-net-sdk-core/DefaultAcsClient.cs b/aliyun-net-sdk-core/DefaultAcsClient.cs index 3f06cc36cd..8a5af49ef3 100644 --- a/aliyun-net-sdk-core/DefaultAcsClient.cs +++ b/aliyun-net-sdk-core/DefaultAcsClient.cs @@ -24,7 +24,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; - +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Auth.Provider; using Aliyun.Acs.Core.Exceptions; @@ -40,7 +40,7 @@ namespace Aliyun.Acs.Core { - public partial class DefaultAcsClient : IAcsClient + public class DefaultAcsClient : IAcsClient { private static readonly HttpWebProxy WebProxy = new HttpWebProxy(); private readonly IClientProfile clientProfile; @@ -329,7 +329,6 @@ public virtual HttpResponse DoAction(AcsRequest request, bool autoRetry, i var watch = Stopwatch.StartNew(); FormatType? requestFormatType = request.AcceptFormat; - format = requestFormatType; var domain = request.ProductDomain ?? Endpoint.FindProductDomain(regionId, request.Product, endpoints); @@ -346,7 +345,7 @@ public virtual HttpResponse DoAction(AcsRequest request, bool autoRetry, i { DictionaryUtil.Add(request.Headers, "x-acs-action", request.ActionName); } - var httpRequest = request.SignRequest(signer, credentials, format, domain); + var httpRequest = request.SignRequest(signer, credentials, requestFormatType, domain); ResolveTimeout(httpRequest, request.Product, request.Version, request.ActionName); SetHttpsInsecure(IgnoreCertificate); ResolveProxy(httpRequest, request); @@ -615,5 +614,225 @@ public static void DisableLogger() { CommonLog.DisableLogger(); } + + #region Async + + public async Task GetAcsResponseAsync(AcsRequest request, CancellationToken cancellationToken) where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetAcsResponseAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, CancellationToken cancellationToken) where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, autoRetry, maxRetryNumber, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetAcsResponseAsync(AcsRequest request, IClientProfile profile, CancellationToken cancellationToken) where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, profile, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetAcsResponseAsync(AcsRequest request, string regionId, Credential credential, CancellationToken cancellationToken) + where T : AcsResponse + { + var httpResponse = await DoActionAsync(request, regionId, credential, cancellationToken).ConfigureAwait(false); + return ParseAcsResponse(request, httpResponse); + } + + public async Task GetCommonResponseAsync(CommonRequest request, CancellationToken cancellationToken) + { + var httpResponse = await DoActionAsync(request.BuildRequest(), cancellationToken).ConfigureAwait(false); + string data = null; + if (httpResponse.Content != null) + { + data = Encoding.UTF8.GetString(httpResponse.Content); + } + + var response = new CommonResponse + { + Data = data, + HttpResponse = httpResponse, + HttpStatus = httpResponse.Status + }; + + return response; + } + + public Task DoActionAsync(AcsRequest request, CancellationToken cancellationToken) where T : AcsResponse + { + return DoActionAsync(request, AutoRetry, MaxRetryNumber, clientProfile, cancellationToken); + } + + public Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, CancellationToken cancellationToken) + where T : AcsResponse + { + return DoActionAsync(request, autoRetry, maxRetryNumber, clientProfile, cancellationToken); + } + + public Task DoActionAsync(AcsRequest request, IClientProfile profile, CancellationToken cancellationToken) where T : AcsResponse + { + return DoActionAsync(request, AutoRetry, MaxRetryNumber, profile, cancellationToken); + } + + public async Task DoActionAsync(AcsRequest request, string regionId, Credential credential, CancellationToken cancellationToken) + where T : AcsResponse + { + var signer = Signer.GetSigner(new LegacyCredentials(credential)); + FormatType? format = null; + if (null == request.RegionId) + { + request.RegionId = regionId; + } + + if (request.ProductDomain == null) + { + request.ProductDomain = EndpointUserConfig.GetProductDomain(request.Product, request.RegionId); + if (request.ProductDomain == null) + { + request.SetProductDomain(); + } + } + + List endpoints = null; + if (null != clientProfile) + { + format = clientProfile.GetFormat(); + if (request.ProductDomain == null) + { + endpoints = await clientProfile.GetEndpointsAsync(request.Product, request.RegionId, request.LocationProduct, + request.LocationEndpointType, cancellationToken).ConfigureAwait(false); + } + } + + return await DoActionAsync(request, AutoRetry, MaxRetryNumber, request.RegionId, credential, signer, format, endpoints, cancellationToken).ConfigureAwait(false); + } + + public async Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, IClientProfile profile, CancellationToken cancellationToken) where T : AcsResponse + { + if (null == profile) + { + throw new ClientException("SDK.InvalidProfile", "No active profile found."); + } + + var retry = autoRetry; + var retryNumber = maxRetryNumber; + var region = profile.GetRegionId(); + if (null == request.RegionId) + { + request.RegionId = region; + } + + if (request.ProductDomain == null) + { + request.ProductDomain = EndpointUserConfig.GetProductDomain(request.Product, request.RegionId); + if (request.ProductDomain == null) + { + request.SetProductDomain(); + } + } + + var credentials = await credentialsProvider.GetCredentialsAsync(cancellationToken).ConfigureAwait(false); + if (credentials == null) + { + credentials = await new DefaultCredentialProvider().GetAlibabaCloudClientCredentialAsync(cancellationToken).ConfigureAwait(false); + } + + var signer = Signer.GetSigner(credentials); + var format = profile.GetFormat(); + List endpoints = null; + + if (request.ProductDomain == null) + { + endpoints = await clientProfile.GetEndpointsAsync(request.Product, request.RegionId, + request.LocationProduct, + request.LocationEndpointType, cancellationToken).ConfigureAwait(false); + } + + return await DoActionAsync(request, retry, retryNumber, request.RegionId, credentials, signer, format, endpoints, cancellationToken).ConfigureAwait(false); + } + + public Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, string regionId, + Credential credential, Signer signer, FormatType? format, List endpoints, CancellationToken cancellationToken) where T : AcsResponse + { + return DoActionAsync(request, autoRetry, maxRetryNumber, regionId, new LegacyCredentials(credential), signer, + format, endpoints, cancellationToken); + } + + public virtual async Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryNumber, + string regionId, + AlibabaCloudCredentials credentials, Signer signer, FormatType? format, List endpoints, + CancellationToken cancellationToken) + where T : AcsResponse + { + var httpStatusCode = ""; + var retryAttemptTimes = 0; + ClientException exception; + RetryPolicyContext retryPolicyContext; + + do + { + try + { + var watch = Stopwatch.StartNew(); + + FormatType? requestFormatType = request.AcceptFormat; + + var domain = request.ProductDomain ?? + Endpoint.FindProductDomain(regionId, request.Product, endpoints); + + if (null == domain) + { + throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access."); + } + + var userAgent = UserAgent.Resolve(request.GetSysUserAgentConfig(), userAgentConfig); + DictionaryUtil.Add(request.Headers, "User-Agent", userAgent); + DictionaryUtil.Add(request.Headers, "x-acs-version", request.Version); + if (!string.IsNullOrWhiteSpace(request.ActionName)) + { + DictionaryUtil.Add(request.Headers, "x-acs-action", request.ActionName); + } + var httpRequest = request.SignRequest(signer, credentials, requestFormatType, domain); + ResolveTimeout(httpRequest, request.Product, request.Version, request.ActionName); + SetHttpsInsecure(IgnoreCertificate); + ResolveProxy(httpRequest, request); + var response = await GetResponseAsync(httpRequest, cancellationToken).ConfigureAwait(false); + + httpStatusCode = response.Status.ToString(); + PrintHttpDebugMsg(request, response); + watch.Stop(); + CommonLog.ExecuteTime = watch.ElapsedMilliseconds; + return response; + } + catch (ClientException ex) + { + retryPolicyContext = new RetryPolicyContext(ex, httpStatusCode, retryAttemptTimes, request.Product, + request.Version, + request.ActionName, RetryCondition.BlankStatus); + + CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); + exception = ex; + } + + await Task.Delay(retryPolicy.GetDelayTimeBeforeNextRetry(retryPolicyContext), cancellationToken).ConfigureAwait(false); + } while ((retryPolicy.ShouldRetry(retryPolicyContext) & RetryCondition.NoRetry) != RetryCondition.NoRetry); + + if (exception != null) + { + CommonLog.LogException(exception, exception.ErrorCode, exception.ErrorMessage); + throw new ClientException(exception.ErrorCode, exception.ErrorMessage); + } + + return null; + } + + public virtual Task GetResponseAsync(HttpRequest httpRequest, CancellationToken cancellationToken) + { + return HttpResponse.GetResponseAsync(httpRequest, cancellationToken); + } + #endregion } } diff --git a/aliyun-net-sdk-core/Http/HttpResponse.Async.cs b/aliyun-net-sdk-core/Http/HttpResponse.Async.cs deleted file mode 100644 index a85cc4facd..0000000000 --- a/aliyun-net-sdk-core/Http/HttpResponse.Async.cs +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using Aliyun.Acs.Core.Exceptions; -using Aliyun.Acs.Core.Utils; - -namespace Aliyun.Acs.Core.Http -{ - public partial class HttpResponse - { - private static async Task ParseHttpResponseAsync(HttpResponse httpResponse, HttpWebResponse httpWebResponse, CancellationToken cancellationToken) - { - httpResponse.Content = await ReadContentAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); - httpResponse.Status = (int)httpWebResponse.StatusCode; - httpResponse.Headers = new Dictionary(); - httpResponse.Method = ParameterHelper.StringToMethodType(httpWebResponse.Method); - httpResponse.HttpVersion = httpWebResponse.ProtocolVersion.ToString(); - - foreach (var key in httpWebResponse.Headers.AllKeys) - { - httpResponse.Headers.Add(key, httpWebResponse.Headers[key]); - } - - var contentType = DictionaryUtil.Get(httpResponse.Headers, "Content-Type"); - - if (null != contentType) - { - httpResponse.Encoding = "UTF-8"; - var split = contentType.Split(';'); - httpResponse.ContentType = ParameterHelper.StingToFormatType(split[0].Trim()); - if (split.Length > 1 && split[1].Contains("=")) - { - var codings = split[1].Split('='); - httpResponse.Encoding = codings[1].Trim().ToUpper(); - } - } - } - - public static async Task ReadContentAsync(HttpResponse response, HttpWebResponse rsp, CancellationToken cancellationToken) - { - using (var ms = new MemoryStream()) - using (var stream = rsp.GetResponseStream()) - { - if (stream == null) - { - return new byte[0]; - } - - await stream.CopyToAsync(ms, bufferLength, cancellationToken).ConfigureAwait(false); - - return ms.ToArray(); - } - } - - public static async Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken = default(CancellationToken), int? timeout = null) - { - var result = await GetWebRequestAsync(request, timeout, cancellationToken).ConfigureAwait(false); - - var httpWebRequest = result.Item1; - - HttpWebResponse httpWebResponse; - var httpResponse = new HttpResponse(httpWebRequest.RequestUri.AbsoluteUri); - - try - { - using (httpWebResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync().ConfigureAwait(false)) - { - await ParseHttpResponseAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); - return httpResponse; - } - } - catch (WebException ex) - { - if (ex.Response != null) - { - using (httpWebResponse = ex.Response as HttpWebResponse) - { - await ParseHttpResponseAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); - return httpResponse; - } - } - - if (result.Item2.IsCancellationRequested) - { - throw new ClientException("SDK.WebException", - string.Format("HttpWebRequest timeout, the request url is {0} {1}", - httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); - } - - throw new ClientException("SDK.WebException", - string.Format("HttpWebRequest WebException occured, the request url is {0} {1}", - httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); - } - catch (IOException ex) - { - throw new ClientException("SDK.ServerUnreachable:", - string.Format("Server unreachable: connection to url: {0} failed. {1}", - httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, - ex)); - } - catch (Exception ex) - { - throw new ClientException("SDK.Exception", - string.Format("The request url is {0} {1}", - httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); - } - finally - { - result.Item2.Dispose(); - } - } - - private static async Task> GetWebRequestAsync(HttpRequest request, int? timeout, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var uri = new Uri(request.Url); - var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri); - - httpWebRequest.Proxy = request.WebProxy; - httpWebRequest.Method = request.Method.ToString(); - httpWebRequest.KeepAlive = true; - - httpWebRequest.Timeout = timeout ?? (request.ConnectTimeout > 0 - ? request.ConnectTimeout - : DEFAULT_CONNECT_TIMEOUT_In_MilliSeconds); - - httpWebRequest.ReadWriteTimeout = - request.ReadTimeout > 0 ? request.ReadTimeout : DEFAULT_READ_TIMEOUT_IN_MilliSeconds; - - if (request.IgnoreCertificate) - { - httpWebRequest.ServerCertificateValidationCallback = (s, cert, chains, sslPolicyError) => true; - } - - if (DictionaryUtil.Get(request.Headers, "Accept") != null) - { - httpWebRequest.Accept = DictionaryUtil.Pop(request.Headers, "Accept"); - } - - if (DictionaryUtil.Get(request.Headers, "Date") != null) - { - var headerDate = DictionaryUtil.Pop(request.Headers, "Date"); - httpWebRequest.Date = Convert.ToDateTime(headerDate); - } - - foreach (var header in request.Headers) - { - if (header.Key.Equals("Content-Length")) - { - httpWebRequest.ContentLength = long.Parse(header.Value); - continue; - } - - if (header.Key.Equals("Content-Type")) - { - httpWebRequest.ContentType = header.Value; - continue; - } - - if (header.Key.Equals("User-Agent")) - { - httpWebRequest.UserAgent = header.Value; - continue; - } - - httpWebRequest.Headers.Add(header.Key, header.Value); - } - - var cts = cancellationToken.CanBeCanceled ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken) : new CancellationTokenSource(); - - cts.CancelAfter(timeout > 0 ? timeout.Value : Math.Max(httpWebRequest.Timeout, httpWebRequest.ReadWriteTimeout)); - - cts.Token.Register(httpWebRequest.Abort); - - if ((request.Method == MethodType.POST || request.Method == MethodType.PUT) && request.Content != null) - { - try - { - using (var stream = await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)) - { - await stream.WriteAsync(request.Content, 0, request.Content.Length, cancellationToken).ConfigureAwait(false); - } - } - catch - { - cts.Dispose(); - - throw; - } - } - - return Tuple.Create(httpWebRequest, cts); - } - } -} diff --git a/aliyun-net-sdk-core/Http/HttpResponse.cs b/aliyun-net-sdk-core/Http/HttpResponse.cs index d2f83c7482..0988b83a76 100644 --- a/aliyun-net-sdk-core/Http/HttpResponse.cs +++ b/aliyun-net-sdk-core/Http/HttpResponse.cs @@ -21,13 +21,14 @@ using System.Collections.Generic; using System.IO; using System.Net; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Utils; namespace Aliyun.Acs.Core.Http { - public partial class HttpResponse : HttpRequest + public class HttpResponse : HttpRequest { // Default read timeout 10s private const int DEFAULT_READ_TIMEOUT_IN_MilliSeconds = 10000; @@ -220,5 +221,193 @@ public bool isSuccess() { return 200 <= Status && 300 > Status; } + + #region Async + + private static async Task ParseHttpResponseAsync(HttpResponse httpResponse, HttpWebResponse httpWebResponse, CancellationToken cancellationToken) + { + httpResponse.Content = await ReadContentAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); + httpResponse.Status = (int)httpWebResponse.StatusCode; + httpResponse.Headers = new Dictionary(); + httpResponse.Method = ParameterHelper.StringToMethodType(httpWebResponse.Method); + httpResponse.HttpVersion = httpWebResponse.ProtocolVersion.ToString(); + + foreach (var key in httpWebResponse.Headers.AllKeys) + { + httpResponse.Headers.Add(key, httpWebResponse.Headers[key]); + } + + var contentType = DictionaryUtil.Get(httpResponse.Headers, "Content-Type"); + + if (null != contentType) + { + httpResponse.Encoding = "UTF-8"; + var split = contentType.Split(';'); + httpResponse.ContentType = ParameterHelper.StingToFormatType(split[0].Trim()); + if (split.Length > 1 && split[1].Contains("=")) + { + var codings = split[1].Split('='); + httpResponse.Encoding = codings[1].Trim().ToUpper(); + } + } + } + + public static async Task ReadContentAsync(HttpResponse response, HttpWebResponse rsp, CancellationToken cancellationToken) + { + using (var ms = new MemoryStream()) + using (var stream = rsp.GetResponseStream()) + { + if (stream == null) + { + return new byte[0]; + } + + await stream.CopyToAsync(ms, bufferLength, cancellationToken).ConfigureAwait(false); + + return ms.ToArray(); + } + } + + public static async Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken, int? timeout = null) + { + var result = await GetWebRequestAsync(request, timeout, cancellationToken).ConfigureAwait(false); + + var httpWebRequest = result.Item1; + + HttpWebResponse httpWebResponse; + var httpResponse = new HttpResponse(httpWebRequest.RequestUri.AbsoluteUri); + + try + { + using (httpWebResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync().ConfigureAwait(false)) + { + await ParseHttpResponseAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); + return httpResponse; + } + } + catch (WebException ex) + { + if (ex.Response != null) + { + using (httpWebResponse = ex.Response as HttpWebResponse) + { + await ParseHttpResponseAsync(httpResponse, httpWebResponse, cancellationToken).ConfigureAwait(false); + return httpResponse; + } + } + + if (result.Item2.IsCancellationRequested) + { + throw new ClientException("SDK.WebException", + string.Format("HttpWebRequest timeout, the request url is {0} {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); + } + + throw new ClientException("SDK.WebException", + string.Format("HttpWebRequest WebException occured, the request url is {0} {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); + } + catch (IOException ex) + { + throw new ClientException("SDK.ServerUnreachable:", + string.Format("Server unreachable: connection to url: {0} failed. {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, + ex)); + } + catch (Exception ex) + { + throw new ClientException("SDK.Exception", + string.Format("The request url is {0} {1}", + httpWebRequest.RequestUri == null ? "empty" : httpWebRequest.RequestUri.Host, ex)); + } + finally + { + result.Item2.Dispose(); + } + } + + private static async Task> GetWebRequestAsync(HttpRequest request, int? timeout, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var uri = new Uri(request.Url); + var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri); + + httpWebRequest.Proxy = request.WebProxy; + httpWebRequest.Method = request.Method.ToString(); + httpWebRequest.KeepAlive = true; + + httpWebRequest.Timeout = timeout ?? (request.ConnectTimeout > 0 + ? request.ConnectTimeout + : DEFAULT_CONNECT_TIMEOUT_In_MilliSeconds); + + httpWebRequest.ReadWriteTimeout = + request.ReadTimeout > 0 ? request.ReadTimeout : DEFAULT_READ_TIMEOUT_IN_MilliSeconds; + + if (request.IgnoreCertificate) + { + httpWebRequest.ServerCertificateValidationCallback = (s, cert, chains, sslPolicyError) => true; + } + + if (DictionaryUtil.Get(request.Headers, "Accept") != null) + { + httpWebRequest.Accept = DictionaryUtil.Pop(request.Headers, "Accept"); + } + + if (DictionaryUtil.Get(request.Headers, "Date") != null) + { + var headerDate = DictionaryUtil.Pop(request.Headers, "Date"); + httpWebRequest.Date = Convert.ToDateTime(headerDate); + } + + foreach (var header in request.Headers) + { + if (header.Key.Equals("Content-Length")) + { + httpWebRequest.ContentLength = long.Parse(header.Value); + continue; + } + + if (header.Key.Equals("Content-Type")) + { + httpWebRequest.ContentType = header.Value; + continue; + } + + if (header.Key.Equals("User-Agent")) + { + httpWebRequest.UserAgent = header.Value; + continue; + } + + httpWebRequest.Headers.Add(header.Key, header.Value); + } + + var cts = cancellationToken.CanBeCanceled ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken) : new CancellationTokenSource(); + + cts.CancelAfter(timeout > 0 ? timeout.Value : Math.Max(httpWebRequest.Timeout, httpWebRequest.ReadWriteTimeout)); + + cts.Token.Register(httpWebRequest.Abort); + + if ((request.Method == MethodType.POST || request.Method == MethodType.PUT) && request.Content != null) + { + try + { + using (var stream = await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)) + { + await stream.WriteAsync(request.Content, 0, request.Content.Length, cancellationToken).ConfigureAwait(false); + } + } + catch + { + cts.Dispose(); + + throw; + } + } + + return Tuple.Create(httpWebRequest, cts); + } + #endregion } } diff --git a/aliyun-net-sdk-core/IAcsClient.Async.cs b/aliyun-net-sdk-core/IAcsClient.Async.cs deleted file mode 100644 index 1506fea787..0000000000 --- a/aliyun-net-sdk-core/IAcsClient.Async.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Aliyun.Acs.Core.Auth; -using Aliyun.Acs.Core.Http; -using Aliyun.Acs.Core.Profile; -using Aliyun.Acs.Core.Regions; - -namespace Aliyun.Acs.Core -{ - public partial interface IAcsClient - { - Task GetAcsResponseAsync(AcsRequest request, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task GetAcsResponseAsync(AcsRequest request, - bool autoRetry, - int maxRetryCounts, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task GetAcsResponseAsync(AcsRequest request, - IClientProfile profile, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task GetAcsResponseAsync(AcsRequest request, - string regionId, - Credential credential, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task GetCommonResponseAsync(CommonRequest request, - CancellationToken cancellationToken = default(CancellationToken)); - - Task DoActionAsync(AcsRequest request, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task DoActionAsync(AcsRequest request, - bool autoRetry, - int maxRetryCounts, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task DoActionAsync(AcsRequest request, - IClientProfile profile, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task DoActionAsync(AcsRequest request, - string regionId, - Credential credential, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task DoActionAsync(AcsRequest request, - bool autoRetry, - int maxRetryCounts, - IClientProfile profile, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - - Task DoActionAsync(AcsRequest request, - bool autoRetry, int maxRetryNumber, - string regionId, Credential credential, - Signer signer, FormatType? format, - List endpoints, - CancellationToken cancellationToken = default(CancellationToken)) - where T : AcsResponse; - } -} diff --git a/aliyun-net-sdk-core/IAcsClient.cs b/aliyun-net-sdk-core/IAcsClient.cs index ac718c9ef6..ed4285713f 100644 --- a/aliyun-net-sdk-core/IAcsClient.cs +++ b/aliyun-net-sdk-core/IAcsClient.cs @@ -18,7 +18,8 @@ */ using System.Collections.Generic; - +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Profile; @@ -26,8 +27,9 @@ namespace Aliyun.Acs.Core { - public partial interface IAcsClient + public interface IAcsClient { + #region Sync T GetAcsResponse(AcsRequest request) where T : AcsResponse; T GetAcsResponse(AcsRequest request, bool autoRetry, int maxRetryCounts) where T : AcsResponse; @@ -54,5 +56,69 @@ HttpResponse DoAction(AcsRequest request, string regionId, Credential credential, Signer signer, FormatType? format, List endpoints) where T : AcsResponse; + #endregion + + #region Async + + Task GetAcsResponseAsync(AcsRequest request, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetAcsResponseAsync(AcsRequest request, + bool autoRetry, + int maxRetryCounts, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetAcsResponseAsync(AcsRequest request, + IClientProfile profile, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetAcsResponseAsync(AcsRequest request, + string regionId, + Credential credential, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task GetCommonResponseAsync(CommonRequest request, + CancellationToken cancellationToken = default(CancellationToken)); + + Task DoActionAsync(AcsRequest request, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + bool autoRetry, + int maxRetryCounts, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + IClientProfile profile, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + string regionId, + Credential credential, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + bool autoRetry, + int maxRetryCounts, + IClientProfile profile, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + + Task DoActionAsync(AcsRequest request, + bool autoRetry, int maxRetryNumber, + string regionId, Credential credential, + Signer signer, FormatType? format, + List endpoints, + CancellationToken cancellationToken = default(CancellationToken)) + where T : AcsResponse; + #endregion } } diff --git a/aliyun-net-sdk-core/Profile/DefaultProfile.cs b/aliyun-net-sdk-core/Profile/DefaultProfile.cs index 6946dab01c..c5e7ddcb2b 100644 --- a/aliyun-net-sdk-core/Profile/DefaultProfile.cs +++ b/aliyun-net-sdk-core/Profile/DefaultProfile.cs @@ -101,7 +101,7 @@ public List GetEndpoints(string product, string regionId, string servi return endpointResolve.Resolve(product, regionId, serviceCode, endpointType, _credential, locationConfig); } - public async Task> GetEndpointsAsync(string product, string regionId, string serviceCode, string endpointType, CancellationToken cancellationToken = default(CancellationToken)) + public async Task> GetEndpointsAsync(string product, string regionId, string serviceCode, string endpointType, CancellationToken cancellationToken) { return await endpointResolve.ResolveAsync(product, regionId, serviceCode, endpointType, _credential, locationConfig, cancellationToken).ConfigureAwait(false); } @@ -111,7 +111,7 @@ public List GetEndpoints(string regionId, string product) return endpointResolve.GetEndpoints(regionId, product); } - public Task> GetEndpointsAsync(string regionId, string product, CancellationToken cancellationToken = default(CancellationToken)) + public Task> GetEndpointsAsync(string regionId, string product, CancellationToken cancellationToken) { return endpointResolve.GetEndpointsAsync(regionId, product, cancellationToken); } @@ -124,8 +124,8 @@ public void AddEndpoint(string endpointName, string regionId, string product, st } public Task AddEndpointAsync(string endpointName, string regionId, string product, string domain, - bool isNeverExpire = false, - CancellationToken cancellationToken = default(CancellationToken)) + bool isNeverExpire, + CancellationToken cancellationToken) { EndpointUserConfig.AddEndpoint(product, regionId, domain); return endpointResolve.AddEndpointAsync(endpointName, regionId, product, domain, isNeverExpire, cancellationToken); diff --git a/aliyun-net-sdk-core/Profile/IClientProfile.cs b/aliyun-net-sdk-core/Profile/IClientProfile.cs index e2579bf1f3..7f4cf66356 100644 --- a/aliyun-net-sdk-core/Profile/IClientProfile.cs +++ b/aliyun-net-sdk-core/Profile/IClientProfile.cs @@ -49,8 +49,8 @@ void AddEndpoint(string endpointName, string regionId, string product, string do bool isNeverExpire = false); Task AddEndpointAsync(string endpointName, string regionId, string product, string domain, - bool isNeverExpire = false, - CancellationToken cancellationToken = default(CancellationToken)); + bool isNeverExpire, + CancellationToken cancellationToken); } } diff --git a/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs b/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs deleted file mode 100644 index 4c07fc0736..0000000000 --- a/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.Async.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Aliyun.Acs.Core.Auth; -using Aliyun.Acs.Core.Exceptions; -using Aliyun.Acs.Core.Regions.Location; -using Aliyun.Acs.Core.Utils; - -namespace Aliyun.Acs.Core.Regions.Endpoints -{ - internal partial class EndpointResolve - { - public async Task> ResolveAsync(string product, string regionId, string serviceCode, string endpointType, - Credential credential, LocationConfig locationConfig, CancellationToken cancellationToken) - { - try - { - if (product == null) - { - return _endpoints; - } - - if (_endpoints.FirstOrDefault(x => x.Name == product) != null) - { - var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); - - if (serviceCode != null && endpoint == null) - { - endpoint = await remoteEndpointProvider.GetEndpointAsync(regionId, product, serviceCode, endpointType, - credential, locationConfig, cancellationToken).ConfigureAwait(false); - } - - if (endpoint != null) - { - foreach (var region in endpoint.RegionIds) - { - foreach (var productDomain in endpoint.ProductDomains.ToList()) - { - AddEndpoint(endpoint.Name, region, product, productDomain.DomainName); - CacheTimeHelper.AddLastClearTimePerProduct(product, region, DateTime.UtcNow); - } - } - } - else - { - throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access."); - } - } - else if (Endpoint.FindProductDomain(regionId, product, _endpoints) == null || - CacheTimeHelper.CheckCacheIsExpire(product, regionId)) - { - var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); - - if (serviceCode != null && endpoint == null) - { - endpoint = await remoteEndpointProvider.GetEndpointAsync(regionId, product, serviceCode, endpointType, - credential, locationConfig, cancellationToken).ConfigureAwait(false); - } - - if (endpoint != null) - { - foreach (var region in endpoint.RegionIds) - { - foreach (var productDomain in endpoint.ProductDomains.ToList()) - { - AddEndpoint(endpoint.Name, region, product, productDomain.DomainName); - CacheTimeHelper.AddLastClearTimePerProduct(product, region, DateTime.UtcNow); - } - } - } - } - } - catch (ClientException ex) - { - CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); - throw new ClientException(ex.ErrorCode, ex.ErrorMessage); - } - - return _endpoints; - } - - public async Task AddEndpointAsync(string endpointName, string regionId, string product, string domain, - bool isNeverExpire = false, - CancellationToken cancellationToken = default(CancellationToken)) - { - if (0 == _endpoints.Count) - { - _endpoints = await GetEndpointsAsync(regionId, product, cancellationToken).ConfigureAwait(false); - } - - var endpoint = FindEndpointByRegionId(regionId); - if (null == endpoint) - { - var regions = new HashSet { regionId }; - - var productDomains = new List { new ProductDomain(product, domain) }; - endpoint = new Endpoint(endpointName, regions, productDomains); - if (_endpoints == null) - { - _endpoints = new List(); - } - - _endpoints.Add(endpoint); - } - else - { - UpdateEndpoint(regionId, product, domain, endpoint); - } - - if (isNeverExpire) - { - var date = DateTime.UtcNow.AddYears(100); - CacheTimeHelper.AddLastClearTimePerProduct(product, regionId, date); - } - } - - public async Task> GetEndpointsAsync(string regionId, string product, CancellationToken cancellationToken) - { - if (null == _endpoints) - { - var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); - if (endpoint != null) - { - _endpoints = new List { endpoint }; - } - } - - return _endpoints; - } - } -} diff --git a/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs b/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs index e6dd313da5..ca6500e073 100644 --- a/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs +++ b/aliyun-net-sdk-core/Regions/Endpoints/EndpointResolve.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Aliyun.Acs.Core.Auth; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Regions.Location; @@ -8,7 +10,7 @@ namespace Aliyun.Acs.Core.Regions.Endpoints { - internal partial class EndpointResolve + internal class EndpointResolve { private static List _endpoints; private readonly IEndpointsProvider internalEndpointProvider; @@ -185,5 +187,126 @@ private static ProductDomain FindProductDomain(List productDomain return null; } + + #region Async + + public async Task> ResolveAsync(string product, string regionId, string serviceCode, string endpointType, + Credential credential, LocationConfig locationConfig, CancellationToken cancellationToken) + { + try + { + if (product == null) + { + return _endpoints; + } + + if (_endpoints.FirstOrDefault(x => x.Name == product) != null) + { + var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); + + if (serviceCode != null && endpoint == null) + { + endpoint = await remoteEndpointProvider.GetEndpointAsync(regionId, product, serviceCode, endpointType, + credential, locationConfig, cancellationToken).ConfigureAwait(false); + } + + if (endpoint != null) + { + foreach (var region in endpoint.RegionIds) + { + foreach (var productDomain in endpoint.ProductDomains.ToList()) + { + AddEndpoint(endpoint.Name, region, product, productDomain.DomainName); + CacheTimeHelper.AddLastClearTimePerProduct(product, region, DateTime.UtcNow); + } + } + } + else + { + throw new ClientException("SDK.InvalidRegionId", "Can not find endpoint to access."); + } + } + else if (Endpoint.FindProductDomain(regionId, product, _endpoints) == null || + CacheTimeHelper.CheckCacheIsExpire(product, regionId)) + { + var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); + + if (serviceCode != null && endpoint == null) + { + endpoint = await remoteEndpointProvider.GetEndpointAsync(regionId, product, serviceCode, endpointType, + credential, locationConfig, cancellationToken).ConfigureAwait(false); + } + + if (endpoint != null) + { + foreach (var region in endpoint.RegionIds) + { + foreach (var productDomain in endpoint.ProductDomains.ToList()) + { + AddEndpoint(endpoint.Name, region, product, productDomain.DomainName); + CacheTimeHelper.AddLastClearTimePerProduct(product, region, DateTime.UtcNow); + } + } + } + } + } + catch (ClientException ex) + { + CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); + throw new ClientException(ex.ErrorCode, ex.ErrorMessage); + } + + return _endpoints; + } + + public async Task AddEndpointAsync(string endpointName, string regionId, string product, string domain, + bool isNeverExpire = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (0 == _endpoints.Count) + { + _endpoints = await GetEndpointsAsync(regionId, product, cancellationToken).ConfigureAwait(false); + } + + var endpoint = FindEndpointByRegionId(regionId); + if (null == endpoint) + { + var regions = new HashSet { regionId }; + + var productDomains = new List { new ProductDomain(product, domain) }; + endpoint = new Endpoint(endpointName, regions, productDomains); + if (_endpoints == null) + { + _endpoints = new List(); + } + + _endpoints.Add(endpoint); + } + else + { + UpdateEndpoint(regionId, product, domain, endpoint); + } + + if (isNeverExpire) + { + var date = DateTime.UtcNow.AddYears(100); + CacheTimeHelper.AddLastClearTimePerProduct(product, regionId, date); + } + } + + public async Task> GetEndpointsAsync(string regionId, string product, CancellationToken cancellationToken) + { + if (null == _endpoints) + { + var endpoint = await internalEndpointProvider.GetEndpointAsync(regionId, product, cancellationToken).ConfigureAwait(false); + if (endpoint != null) + { + _endpoints = new List { endpoint }; + } + } + + return _endpoints; + } + #endregion } } From dad516227c027bb0fe7afd0e715f2af54345b37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 14:18:05 +0800 Subject: [PATCH 6/8] fix build fail --- aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs b/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs index 62fa159fcc..6ff30cc23f 100644 --- a/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs +++ b/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs @@ -38,7 +38,7 @@ public async Task TestConnectTimeoutWithException() request.Method = MethodType.GET; request.SetConnectTimeoutInMilliSeconds(1); - var exception = await Assert.ThrowsAsync(() => HttpResponse.GetResponseAsync(request)); + var exception = await Assert.ThrowsAsync(() => HttpResponse.GetResponseAsync(request, default)); Assert.NotNull(exception.Message); @@ -59,7 +59,7 @@ public async Task TestVPCConnectTimeoutWithException() var request = new DescribeAccessPointsRequest(); request.SetConnectTimeoutInMilliSeconds(1); - Exception exception = await Assert.ThrowsAsync(() => FeatureTest.DefaultClient.GetAcsResponseAsync(request)); + Exception exception = await Assert.ThrowsAsync(() => FeatureTest.DefaultClient.GetAcsResponseAsync(request, default)); Assert.NotNull(exception.Message); From 1b022bcd0516f0826409a5eced4c3919b37ac1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 15:08:36 +0800 Subject: [PATCH 7/8] Fix `Codacy/PR Quality Review` check --- aliyun-net-sdk-core/AcsClientExtensions.cs | 91 +++++++++++++++++++ .../Provider/RsaKeyPairCredentialProvider.cs | 6 +- aliyun-net-sdk-core/Http/HttpResponse.cs | 12 ++- aliyun-net-sdk-core/Profile/IClientProfile.cs | 2 +- .../Timeout/TimeoutTest.Async.cs | 5 +- 5 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 aliyun-net-sdk-core/AcsClientExtensions.cs diff --git a/aliyun-net-sdk-core/AcsClientExtensions.cs b/aliyun-net-sdk-core/AcsClientExtensions.cs new file mode 100644 index 0000000000..f031ff3c3f --- /dev/null +++ b/aliyun-net-sdk-core/AcsClientExtensions.cs @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Aliyun.Acs.Core.Auth; +using Aliyun.Acs.Core.Http; +using Aliyun.Acs.Core.Profile; +using Aliyun.Acs.Core.Regions; + +namespace Aliyun.Acs.Core +{ + public static class AcsClientExtensions + { + public static Task GetAcsResponseAsync(this IAcsClient client, AcsRequest request) where T : AcsResponse + { + return client.GetAcsResponseAsync(request, default(CancellationToken)); + } + + public static Task GetAcsResponseAsync(this IAcsClient client, AcsRequest request, bool autoRetry, int maxRetryCounts) where T : AcsResponse + { + return client.GetAcsResponseAsync(request, autoRetry, maxRetryCounts, default(CancellationToken)); + } + + public static Task GetAcsResponseAsync(this IAcsClient client, AcsRequest request, IClientProfile profile) where T : AcsResponse + { + return client.GetAcsResponseAsync(request, profile, default(CancellationToken)); + } + + public static Task GetAcsResponseAsync(this IAcsClient client, AcsRequest request, string regionId, Credential credential) where T : AcsResponse + { + return client.GetAcsResponseAsync(request, regionId, credential, default(CancellationToken)); + } + + public static Task GetCommonResponseAsync(this IAcsClient client, CommonRequest request) + { + return client.GetCommonResponseAsync(request, default(CancellationToken)); + } + + public static Task DoActionAsync(this IAcsClient client, AcsRequest request) where T : AcsResponse + { + return client.DoActionAsync(request, default(CancellationToken)); + } + + public static Task DoActionAsync(this IAcsClient client, AcsRequest request, bool autoRetry, int maxRetryCounts) where T : AcsResponse + { + return client.DoActionAsync(request, autoRetry, maxRetryCounts, default(CancellationToken)); + } + + public static Task DoActionAsync(this IAcsClient client, AcsRequest request, IClientProfile profile) where T : AcsResponse + { + return client.DoActionAsync(request, profile, default(CancellationToken)); + } + + public static Task DoActionAsync(this IAcsClient client, AcsRequest request, string regionId, Credential credential) where T : AcsResponse + { + return client.DoActionAsync(request, regionId, credential, default(CancellationToken)); + } + + public static Task DoActionAsync(this IAcsClient client, AcsRequest request, bool autoRetry, int maxRetryCounts, IClientProfile profile) where T : AcsResponse + { + return client.DoActionAsync(request, autoRetry, maxRetryCounts, profile, default(CancellationToken)); + } + + public static Task DoActionAsync(this IAcsClient client, AcsRequest request, + bool autoRetry, int maxRetryNumber, + string regionId, Credential credential, + Signer signer, FormatType? format, + List endpoints) where T : AcsResponse + { + return client.DoActionAsync(request, autoRetry, maxRetryNumber, regionId, credential, signer, format, endpoints, default(CancellationToken)); + } + } +} diff --git a/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs index 7446cb7524..58709df921 100644 --- a/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/RsaKeyPairCredentialProvider.cs @@ -58,7 +58,7 @@ public async Task GetCredentialsAsync(CancellationToken { if (basicSessionCredentials == null || basicSessionCredentials.WillSoonExpire()) { - basicSessionCredentials = await GetNewSessionCredentialsAsync().ConfigureAwait(false); + basicSessionCredentials = await GetNewSessionCredentialsAsync(cancellationToken).ConfigureAwait(false); } return basicSessionCredentials; @@ -92,7 +92,7 @@ private BasicSessionCredentials GetNewSessionCredentials() ); } - private async Task GetNewSessionCredentialsAsync() + private async Task GetNewSessionCredentialsAsync(CancellationToken cancellationToken) { var request = new GetSessionAccessKeyRequest { @@ -101,7 +101,7 @@ private async Task GetNewSessionCredentialsAsync() Protocol = ProtocolType.HTTPS }; - var response = await stsClient.GetAcsResponseAsync(request).ConfigureAwait(false); + var response = await stsClient.GetAcsResponseAsync(request, cancellationToken).ConfigureAwait(false); return new BasicSessionCredentials( response.SessionAccesskey.SessionAccessKeyId, diff --git a/aliyun-net-sdk-core/Http/HttpResponse.cs b/aliyun-net-sdk-core/Http/HttpResponse.cs index 0988b83a76..2e458b3afc 100644 --- a/aliyun-net-sdk-core/Http/HttpResponse.cs +++ b/aliyun-net-sdk-core/Http/HttpResponse.cs @@ -268,7 +268,17 @@ public static async Task ReadContentAsync(HttpResponse response, HttpWeb } } - public static async Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken, int? timeout = null) + public static Task GetResponseAsync(HttpRequest request) + { + return GetResponseAsync(request, default(CancellationToken), null); + } + + public static Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken) + { + return GetResponseAsync(request, cancellationToken, null); + } + + public static async Task GetResponseAsync(HttpRequest request, CancellationToken cancellationToken, int? timeout) { var result = await GetWebRequestAsync(request, timeout, cancellationToken).ConfigureAwait(false); diff --git a/aliyun-net-sdk-core/Profile/IClientProfile.cs b/aliyun-net-sdk-core/Profile/IClientProfile.cs index 7f4cf66356..da810b1129 100644 --- a/aliyun-net-sdk-core/Profile/IClientProfile.cs +++ b/aliyun-net-sdk-core/Profile/IClientProfile.cs @@ -39,7 +39,7 @@ public interface IClientProfile List GetEndpoints(string product, string regionId, string serviceCode, string endpointType); - Task> GetEndpointsAsync(string product, string regionId, string serviceCode, string endpointType, CancellationToken cancellationToken = default(CancellationToken)); + Task> GetEndpointsAsync(string product, string regionId, string serviceCode, string endpointType, CancellationToken cancellationToken); void SetLocationConfig(string regionId, string product, string endpoint); diff --git a/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs b/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs index 6ff30cc23f..740b30d3fe 100644 --- a/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs +++ b/aliyun-sdk-feature-test/Timeout/TimeoutTest.Async.cs @@ -20,6 +20,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Aliyun.Acs.Core; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Vpc.Model.V20160428; @@ -38,7 +39,7 @@ public async Task TestConnectTimeoutWithException() request.Method = MethodType.GET; request.SetConnectTimeoutInMilliSeconds(1); - var exception = await Assert.ThrowsAsync(() => HttpResponse.GetResponseAsync(request, default)); + var exception = await Assert.ThrowsAsync(() => HttpResponse.GetResponseAsync(request)); Assert.NotNull(exception.Message); @@ -59,7 +60,7 @@ public async Task TestVPCConnectTimeoutWithException() var request = new DescribeAccessPointsRequest(); request.SetConnectTimeoutInMilliSeconds(1); - Exception exception = await Assert.ThrowsAsync(() => FeatureTest.DefaultClient.GetAcsResponseAsync(request, default)); + Exception exception = await Assert.ThrowsAsync(() => FeatureTest.DefaultClient.GetAcsResponseAsync(request)); Assert.NotNull(exception.Message); From 4aed01fd05ce59f9526dd9c46722f567c8f40d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=BC=9F?= Date: Fri, 16 Oct 2020 15:17:23 +0800 Subject: [PATCH 8/8] remove default --- aliyun-net-sdk-core/IAcsClient.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/aliyun-net-sdk-core/IAcsClient.cs b/aliyun-net-sdk-core/IAcsClient.cs index ed4285713f..5464e62b85 100644 --- a/aliyun-net-sdk-core/IAcsClient.cs +++ b/aliyun-net-sdk-core/IAcsClient.cs @@ -61,55 +61,55 @@ HttpResponse DoAction(AcsRequest request, #region Async Task GetAcsResponseAsync(AcsRequest request, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task GetAcsResponseAsync(AcsRequest request, bool autoRetry, int maxRetryCounts, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task GetAcsResponseAsync(AcsRequest request, IClientProfile profile, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task GetAcsResponseAsync(AcsRequest request, string regionId, Credential credential, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task GetCommonResponseAsync(CommonRequest request, - CancellationToken cancellationToken = default(CancellationToken)); + CancellationToken cancellationToken); Task DoActionAsync(AcsRequest request, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryCounts, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task DoActionAsync(AcsRequest request, IClientProfile profile, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task DoActionAsync(AcsRequest request, string regionId, Credential credential, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task DoActionAsync(AcsRequest request, bool autoRetry, int maxRetryCounts, IClientProfile profile, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; Task DoActionAsync(AcsRequest request, @@ -117,7 +117,7 @@ Task DoActionAsync(AcsRequest request, string regionId, Credential credential, Signer signer, FormatType? format, List endpoints, - CancellationToken cancellationToken = default(CancellationToken)) + CancellationToken cancellationToken) where T : AcsResponse; #endregion }