diff options
author | dakovalkov <dakovalkov@yandex-team.com> | 2023-12-03 13:33:55 +0300 |
---|---|---|
committer | dakovalkov <dakovalkov@yandex-team.com> | 2023-12-03 14:04:39 +0300 |
commit | 2a718325637e5302334b6d0a6430f63168f8dbb3 (patch) | |
tree | 64be81080b7df9ec1d86d053a0c394ae53fcf1fe /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client | |
parent | e0d94a470142d95c3007e9c5d80380994940664a (diff) | |
download | ydb-2a718325637e5302334b6d0a6430f63168f8dbb3.tar.gz |
Update contrib/libs/aws-sdk-cpp to 1.11.37
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client')
12 files changed, 1917 insertions, 441 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp index 4b2a38b4e6..d1a6f262c9 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSClient.cpp @@ -7,11 +7,13 @@ #include <aws/core/AmazonWebServiceRequest.h> #include <aws/core/auth/AWSAuthSigner.h> #include <aws/core/auth/AWSAuthSignerProvider.h> +#include <aws/core/client/AWSUrlPresigner.h> #include <aws/core/client/AWSError.h> #include <aws/core/client/AWSErrorMarshaller.h> #include <aws/core/client/ClientConfiguration.h> #include <aws/core/client/CoreErrors.h> #include <aws/core/client/RetryStrategy.h> +#include <aws/core/client/RequestCompression.h> #include <aws/core/http/HttpClient.h> #include <aws/core/http/HttpClientFactory.h> #include <aws/core/http/HttpResponse.h> @@ -27,6 +29,9 @@ #include <aws/core/Globals.h> #include <aws/core/utils/EnumParseOverflowContainer.h> #include <aws/core/utils/crypto/MD5.h> +#include <aws/core/utils/crypto/CRC32.h> +#include <aws/core/utils/crypto/Sha256.h> +#include <aws/core/utils/crypto/Sha1.h> #include <aws/core/utils/HashingUtils.h> #include <aws/core/utils/crypto/Factories.h> #include <aws/core/utils/event/EventStream.h> @@ -35,10 +40,12 @@ #include <aws/core/Region.h> #include <aws/core/utils/DNS.h> #include <aws/core/Version.h> +#include <aws/core/platform/Environment.h> #include <aws/core/platform/OSVersionInfo.h> #include <cstring> #include <cassert> +#include <iomanip> using namespace Aws; using namespace Aws::Client; @@ -51,12 +58,15 @@ static const int SUCCESS_RESPONSE_MIN = 200; static const int SUCCESS_RESPONSE_MAX = 299; static const char AWS_CLIENT_LOG_TAG[] = "AWSClient"; +static const char AWS_LAMBDA_FUNCTION_NAME[] = "AWS_LAMBDA_FUNCTION_NAME"; +static const char X_AMZN_TRACE_ID[] = "_X_AMZN_TRACE_ID"; + //4 Minutes static const std::chrono::milliseconds TIME_DIFF_MAX = std::chrono::minutes(4); //-4 Minutes static const std::chrono::milliseconds TIME_DIFF_MIN = std::chrono::minutes(-4); -static CoreErrors GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCode) +CoreErrors AWSClient::GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCode) { switch (responseCode) { @@ -70,6 +80,14 @@ static CoreErrors GuessBodylessErrorType(Aws::Http::HttpResponseCode responseCod } } +bool AWSClient::DoesResponseGenerateError(const std::shared_ptr<HttpResponse>& response) +{ + if (response->HasClientError()) return true; + + int responseCode = static_cast<int>(response->GetResponseCode()); + return responseCode < SUCCESS_RESPONSE_MIN || responseCode > SUCCESS_RESPONSE_MAX; +} + struct RequestInfo { Aws::Utils::DateTime ttl; @@ -107,9 +125,10 @@ AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, m_customizedUserAgent(!m_userAgent.empty()), m_hash(Aws::Utils::Crypto::CreateMD5Implementation()), m_requestTimeoutMs(configuration.requestTimeoutMs), - m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment) + m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment), + m_requestCompressionConfig(configuration.requestCompressionConfig) { - SetServiceClientName("AWSBaseClient"); + AWSClient::SetServiceClientName("AWSBaseClient"); } AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, @@ -126,9 +145,10 @@ AWSClient::AWSClient(const Aws::Client::ClientConfiguration& configuration, m_customizedUserAgent(!m_userAgent.empty()), m_hash(Aws::Utils::Crypto::CreateMD5Implementation()), m_requestTimeoutMs(configuration.requestTimeoutMs), - m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment) + m_enableClockSkewAdjustment(configuration.enableClockSkewAdjustment), + m_requestCompressionConfig(configuration.requestCompressionConfig) { - SetServiceClientName("AWSBaseClient"); + AWSClient::SetServiceClientName("AWSBaseClient"); } void AWSClient::SetServiceClientName(const Aws::String& name) @@ -136,10 +156,7 @@ void AWSClient::SetServiceClientName(const Aws::String& name) m_serviceName = name; if (!m_customizedUserAgent) { - Aws::StringStream ss; - ss << "aws-sdk-cpp/" << Version::GetVersionString() << " " << Aws::OSVersionInfo::ComputeOSVersionString() - << " " << Version::GetCompilerVersionString(); - m_userAgent = ss.str(); + m_userAgent = Aws::Client::ComputeUserAgentString(); } } @@ -232,16 +249,24 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, const char* signerRegion = signerRegionOverride; Aws::String regionFromResponse; - Aws::String invocationId = UUID::RandomUUID(); + Aws::String invocationId = Aws::Utils::UUID::RandomUUID(); RequestInfo requestInfo; requestInfo.attempt = 1; requestInfo.maxAttempts = 0; httpRequest->SetHeaderValue(Http::SDK_INVOCATION_ID_HEADER, invocationId); httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo); + AppendRecursionDetectionHeader(httpRequest); for (long retries = 0;; retries++) { - m_retryStrategy->GetSendToken(); + if(!m_retryStrategy->HasSendToken()) + { + return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::SLOW_DOWN, + "", + "Unable to acquire enough send tokens to execute request.", + false/*retryable*/)); + + }; httpRequest->SetEventStreamRequest(request.IsEventStreamRequest()); outcome = AttemptOneRequest(httpRequest, request, signerName, signerRegion, signerServiceNameOverride); @@ -358,16 +383,24 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, const char* signerRegion = signerRegionOverride; Aws::String regionFromResponse; - Aws::String invocationId = UUID::RandomUUID(); + Aws::String invocationId = Aws::Utils::UUID::RandomUUID(); RequestInfo requestInfo; requestInfo.attempt = 1; requestInfo.maxAttempts = 0; httpRequest->SetHeaderValue(Http::SDK_INVOCATION_ID_HEADER, invocationId); httpRequest->SetHeaderValue(Http::SDK_REQUEST_HEADER, requestInfo); + AppendRecursionDetectionHeader(httpRequest); for (long retries = 0;; retries++) { - m_retryStrategy->GetSendToken(); + if(!m_retryStrategy->HasSendToken()) + { + return HttpResponseOutcome(AWSError<CoreErrors>(CoreErrors::SLOW_DOWN, + "", + "Unable to acquire enough send tokens to execute request.", + false/*retryable*/)); + + }; outcome = AttemptOneRequest(httpRequest, signerName, requestName, signerRegion, signerServiceNameOverride); if (retries == 0) { @@ -452,15 +485,6 @@ HttpResponseOutcome AWSClient::AttemptExhaustively(const Aws::Http::URI& uri, return outcome; } -static bool DoesResponseGenerateError(const std::shared_ptr<HttpResponse>& response) -{ - if (response->HasClientError()) return true; - - int responseCode = static_cast<int>(response->GetResponseCode()); - return responseCode < SUCCESS_RESPONSE_MIN || responseCode > SUCCESS_RESPONSE_MAX; - -} - HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<HttpRequest>& httpRequest, const Aws::AmazonWebServiceRequest& request, const char* signerName, const char* signerRegionOverride, const char* signerServiceNameOverride) const { @@ -481,7 +505,31 @@ HttpResponseOutcome AWSClient::AttemptOneRequest(const std::shared_ptr<HttpReque std::shared_ptr<HttpResponse> httpResponse( m_httpClient->MakeRequest(httpRequest, m_readRateLimiter.get(), m_writeRateLimiter.get())); - if (DoesResponseGenerateError(httpResponse)) + if (request.ShouldValidateResponseChecksum()) + { + for (const auto& hashIterator : httpRequest->GetResponseValidationHashes()) + { + Aws::String checksumHeaderKey = Aws::String("x-amz-checksum-") + hashIterator.first; + // TODO: If checksum ends with -#, then skip + if (httpResponse->HasHeader(checksumHeaderKey.c_str())) + { + Aws::String checksumHeaderValue = httpResponse->GetHeader(checksumHeaderKey.c_str()); + if (HashingUtils::Base64Encode(hashIterator.second->GetHash().GetResult()) != checksumHeaderValue) + { + AWSError<CoreErrors> error(CoreErrors::VALIDATION, "", "Response checksums mismatch", false/*retryable*/); + error.SetResponseHeaders(httpResponse->GetHeaders()); + error.SetResponseCode(httpResponse->GetResponseCode()); + error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost()); + AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error); + return HttpResponseOutcome(error); + } + // Validate only a single checksum returned in an HTTP response + break; + } + } + } + + if (DoesResponseGenerateError(httpResponse) || request.HasEmbeddedError(httpResponse->GetResponseBody(), httpResponse->GetHeaders())) { AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response"); auto error = BuildAWSError(httpResponse); @@ -560,6 +608,54 @@ StreamOutcome AWSClient::MakeRequestWithUnparsedResponse(const Aws::Http::URI& u return StreamOutcome(std::move(httpResponseOutcome)); } +StreamOutcome AWSClient::MakeRequestWithUnparsedResponse(const Aws::AmazonWebServiceRequest& request, + const Aws::Endpoint::AWSEndpoint& endpoint, + Http::HttpMethod method, + const char* signerName, + const char* signerRegionOverride, + const char* signerServiceNameOverride) const +{ + const Aws::Http::URI& uri = endpoint.GetURI(); + if (endpoint.GetAttributes()) { + signerName = endpoint.GetAttributes()->authScheme.GetName().c_str(); + if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningName()) { + signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str(); + } + } + + return MakeRequestWithUnparsedResponse(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride); +} + +XmlOutcome AWSXMLClient::MakeRequestWithEventStream(const Aws::AmazonWebServiceRequest& request, + const Aws::Endpoint::AWSEndpoint& endpoint, + Http::HttpMethod method, + const char* signerName, + const char* signerRegionOverride, + const char* signerServiceNameOverride) const +{ + const Aws::Http::URI& uri = endpoint.GetURI(); + if (endpoint.GetAttributes()) { + signerName = endpoint.GetAttributes()->authScheme.GetName().c_str(); + if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningName()) { + signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str(); + } + } + + return MakeRequestWithEventStream(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride); +} + XmlOutcome AWSXMLClient::MakeRequestWithEventStream(const Aws::Http::URI& uri, const Aws::AmazonWebServiceRequest& request, Http::HttpMethod method, @@ -603,6 +699,119 @@ void AWSClient::AddHeadersToRequest(const std::shared_ptr<Aws::Http::HttpRequest AddCommonHeaders(*httpRequest); } +void AWSClient::AppendHeaderValueToRequest(const std::shared_ptr<HttpRequest> &httpRequest, const String header, const String value) const +{ + if (!httpRequest->HasHeader(header.c_str())) + { + httpRequest->SetHeaderValue(header, value); + } + else + { + Aws::String contentEncoding = httpRequest->GetHeaderValue(header.c_str()); + contentEncoding.append(",").append(value); + httpRequest->SetHeaderValue(header, contentEncoding); + } +} + +void AWSClient::AddChecksumToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest, + const Aws::AmazonWebServiceRequest& request) const +{ + Aws::String checksumAlgorithmName = Aws::Utils::StringUtils::ToLower(request.GetChecksumAlgorithmName().c_str()); + + // Request checksums + if (!checksumAlgorithmName.empty()) + { + // For non-streaming payload, the resolved checksum location is always header. + // For streaming payload, the resolved checksum location depends on whether it is an unsigned payload, we let AwsAuthSigner decide it. + if (checksumAlgorithmName == "crc32") + { + if (request.IsStreaming()) + { + httpRequest->SetRequestHash("crc32", Aws::MakeShared<Crypto::CRC32>(AWS_CLIENT_LOG_TAG)); + } + else + { + httpRequest->SetHeaderValue("x-amz-checksum-crc32", HashingUtils::Base64Encode(HashingUtils::CalculateCRC32(*(GetBodyStream(request))))); + } + } + else if (checksumAlgorithmName == "crc32c") + { + if (request.IsStreaming()) + { + httpRequest->SetRequestHash("crc32c", Aws::MakeShared<Crypto::CRC32C>(AWS_CLIENT_LOG_TAG)); + } + else + { + httpRequest->SetHeaderValue("x-amz-checksum-crc32c", HashingUtils::Base64Encode(HashingUtils::CalculateCRC32C(*(GetBodyStream(request))))); + } + } + else if (checksumAlgorithmName == "sha256") + { + if (request.IsStreaming()) + { + httpRequest->SetRequestHash("sha256", Aws::MakeShared<Crypto::Sha256>(AWS_CLIENT_LOG_TAG)); + } + else + { + httpRequest->SetHeaderValue("x-amz-checksum-sha256", HashingUtils::Base64Encode(HashingUtils::CalculateSHA256(*(GetBodyStream(request))))); + } + } + else if (checksumAlgorithmName == "sha1") + { + if (request.IsStreaming()) + { + httpRequest->SetRequestHash("sha1", Aws::MakeShared<Crypto::Sha1>(AWS_CLIENT_LOG_TAG)); + } + else + { + httpRequest->SetHeaderValue("x-amz-checksum-sha1", HashingUtils::Base64Encode(HashingUtils::CalculateSHA1(*(GetBodyStream(request))))); + } + } + else if (checksumAlgorithmName == "md5") + { + httpRequest->SetHeaderValue(Http::CONTENT_MD5_HEADER, HashingUtils::Base64Encode(HashingUtils::CalculateMD5(*(GetBodyStream(request))))); + } + else + { + AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Checksum algorithm: " << checksumAlgorithmName << "is not supported by SDK."); + } + } + + // Response checksums + if (request.ShouldValidateResponseChecksum()) + { + for (const Aws::String& responseChecksumAlgorithmName : request.GetResponseChecksumAlgorithmNames()) + { + checksumAlgorithmName = Aws::Utils::StringUtils::ToLower(responseChecksumAlgorithmName.c_str()); + + if (checksumAlgorithmName == "crc32c") + { + std::shared_ptr<Aws::Utils::Crypto::CRC32C> crc32c = Aws::MakeShared<Aws::Utils::Crypto::CRC32C>(AWS_CLIENT_LOG_TAG); + httpRequest->AddResponseValidationHash("crc32c", crc32c); + } + else if (checksumAlgorithmName == "crc32") + { + std::shared_ptr<Aws::Utils::Crypto::CRC32> crc32 = Aws::MakeShared<Aws::Utils::Crypto::CRC32>(AWS_CLIENT_LOG_TAG); + httpRequest->AddResponseValidationHash("crc", crc32); + } + else if (checksumAlgorithmName == "sha1") + { + std::shared_ptr<Aws::Utils::Crypto::Sha1> sha1 = Aws::MakeShared<Aws::Utils::Crypto::Sha1>(AWS_CLIENT_LOG_TAG); + httpRequest->AddResponseValidationHash("sha1", sha1); + } + else if (checksumAlgorithmName == "sha256") + { + std::shared_ptr<Aws::Utils::Crypto::Sha256> sha256 = Aws::MakeShared<Aws::Utils::Crypto::Sha256>(AWS_CLIENT_LOG_TAG); + httpRequest->AddResponseValidationHash("sha256", sha256); + } + else + { + AWS_LOGSTREAM_WARN(AWS_CLIENT_LOG_TAG, "Checksum algorithm: " << checksumAlgorithmName << " is not supported in validating response body yet."); + } + } + } +} + void AWSClient::AddContentBodyToRequest(const std::shared_ptr<Aws::Http::HttpRequest>& httpRequest, const std::shared_ptr<Aws::IOStream>& body, bool needsContentMd5, bool isChunked) const { @@ -610,7 +819,7 @@ void AWSClient::AddContentBodyToRequest(const std::shared_ptr<Aws::Http::HttpReq //If there is no body, we have a content length of 0 //note: we also used to remove content-type, but S3 actually needs content-type on InitiateMultipartUpload and it isn't - //forbiden by the spec. If we start getting weird errors related to this, make sure it isn't caused by this removal. + //forbidden by the spec. If we start getting weird errors related to this, make sure it isn't caused by this removal. if (!body) { AWS_LOGSTREAM_TRACE(AWS_CLIENT_LOG_TAG, "No content body, content-length headers"); @@ -682,11 +891,11 @@ Aws::String Aws::Client::GetAuthorizationHeader(const Aws::Http::HttpRequest& ht return authHeader.substr(signaturePosition + strlen(Aws::Auth::SIGNATURE) + 1); } -void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, - const std::shared_ptr<HttpRequest>& httpRequest) const +void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, const std::shared_ptr<HttpRequest>& httpRequest) const { - //do headers first since the request likely will set content-length as it's own header. + //do headers first since the request likely will set content-length as its own header. AddHeadersToRequest(httpRequest, request.GetHeaders()); + AddHeadersToRequest(httpRequest, request.GetAdditionalCustomHeaders()); if (request.IsEventStreamRequest()) { @@ -694,9 +903,31 @@ void AWSClient::BuildHttpRequest(const Aws::AmazonWebServiceRequest& request, } else { - AddContentBodyToRequest(httpRequest, request.GetBody(), request.ShouldComputeContentMd5(), request.IsStreaming() && request.IsChunked() && m_httpClient->SupportsChunkedTransferEncoding()); + //Check if compression is required + CompressionAlgorithm selectedCompressionAlgorithm = + request.GetSelectedCompressionAlgorithm(m_requestCompressionConfig); + if (Aws::Client::CompressionAlgorithm::NONE != selectedCompressionAlgorithm) { + Aws::Client::RequestCompression rc; + auto compressOutcome = rc.compress(request.GetBody(), selectedCompressionAlgorithm); + + if (compressOutcome.IsSuccess()) { + Aws::String compressionAlgorithmId = Aws::Client::GetCompressionAlgorithmId(selectedCompressionAlgorithm); + AppendHeaderValueToRequest(httpRequest, CONTENT_ENCODING_HEADER, compressionAlgorithmId); + AddContentBodyToRequest( + httpRequest, compressOutcome.GetResult(), + request.ShouldComputeContentMd5(), + request.IsStreaming() && request.IsChunked() && + m_httpClient->SupportsChunkedTransferEncoding()); + } else { + AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Failed to compress request, submitting uncompressed"); + AddContentBodyToRequest(httpRequest, request.GetBody(), request.ShouldComputeContentMd5(), request.IsStreaming() && request.IsChunked() && m_httpClient->SupportsChunkedTransferEncoding()); + } + } else { + AddContentBodyToRequest(httpRequest, request.GetBody(), request.ShouldComputeContentMd5(), request.IsStreaming() && request.IsChunked() && m_httpClient->SupportsChunkedTransferEncoding()); + } } + AddChecksumToRequest(httpRequest, request); // Pass along handlers for processing data sent/received in bytes httpRequest->SetDataReceivedEventHandler(request.GetDataReceivedEventHandler()); httpRequest->SetDataSentEventHandler(request.GetDataSentEventHandler()); @@ -710,389 +941,132 @@ void AWSClient::AddCommonHeaders(HttpRequest& httpRequest) const httpRequest.SetUserAgent(m_userAgent); } -Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, long long expirationInSeconds) +Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, long long expirationInSeconds) { - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, expirationInSeconds)) - { - return request->GetURIString(); - } - - return {}; -} - -Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) -{ - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - for (const auto& it: customizedHeaders) - { - request->SetHeaderValue(it.first.c_str(), it.second); - } - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, expirationInSeconds)) - { - return request->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, expirationInSeconds); } -Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const char* region, long long expirationInSeconds) const +Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) { - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, region, expirationInSeconds)) - { - return request->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, customizedHeaders, expirationInSeconds); } -Aws::String AWSClient::GeneratePresignedUrl(URI& uri, HttpMethod method, const char* region, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) +Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, const char* region, long long expirationInSeconds) const { - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - for (const auto& it: customizedHeaders) - { - request->SetHeaderValue(it.first.c_str(), it.second); - } - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, region, expirationInSeconds)) - { - return request->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, expirationInSeconds); } -Aws::String AWSClient::GeneratePresignedUrl(Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, long long expirationInSeconds) const +Aws::String AWSClient::GeneratePresignedUrl(const URI& uri, HttpMethod method, const char* region, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) { - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds)) - { - return request->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, customizedHeaders, expirationInSeconds); } -Aws::String AWSClient::GeneratePresignedUrl(Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) +Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, long long expirationInSeconds) const { - std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - for (const auto& it: customizedHeaders) - { - request->SetHeaderValue(it.first.c_str(), it.second); - } - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds)) - { - return request->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, expirationInSeconds); } -Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, - const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const +Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) { - std::shared_ptr<HttpRequest> httpRequest = - ConvertToRequestForPresigning(request, uri, method, extraParams); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*httpRequest, region, expirationInSeconds)) - { - return httpRequest->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, customizedHeaders, expirationInSeconds); } -Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, -const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const +Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const char* signerName, long long expirationInSeconds) const { - std::shared_ptr<HttpRequest> httpRequest = - ConvertToRequestForPresigning(request, uri, method, extraParams); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*httpRequest, region, serviceName, expirationInSeconds)) - { - return httpRequest->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, signerName, expirationInSeconds); } -Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, Aws::Http::HttpMethod method, - const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const +Aws::String AWSClient::GeneratePresignedUrl(const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, const char* signerName, const Aws::Http::HeaderValueCollection& customizedHeaders, long long expirationInSeconds) { - std::shared_ptr<HttpRequest> httpRequest = - ConvertToRequestForPresigning(request, uri, method, extraParams); - auto signer = GetSignerByName(Aws::Auth::SIGV4_SIGNER); - if (signer->PresignRequest(*httpRequest, expirationInSeconds)) - { - return httpRequest->GetURIString(); - } - - return {}; + return AWSUrlPresigner(*this).GeneratePresignedUrl(uri, method, region, serviceName, signerName, customizedHeaders, expirationInSeconds); } -std::shared_ptr<Aws::Http::HttpRequest> AWSClient::ConvertToRequestForPresigning(const Aws::AmazonWebServiceRequest& request, Aws::Http::URI& uri, - Aws::Http::HttpMethod method, const Aws::Http::QueryStringParameterCollection& extraParams) const +Aws::String AWSClient::GeneratePresignedUrl(const Aws::Endpoint::AWSEndpoint& endpoint, + Aws::Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */, + const Aws::Http::HeaderValueCollection& customizedHeaders /* = {} */, + uint64_t expirationInSeconds /* = 0 */, + const char* signerName /* = Aws::Auth::SIGV4_SIGNER */, + const char* signerRegionOverride /* = nullptr */, + const char* signerServiceNameOverride /* = nullptr */) { - request.PutToPresignedUrl(uri); - std::shared_ptr<HttpRequest> httpRequest = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); - - for (auto& param : extraParams) - { - httpRequest->AddQueryStringParameter(param.first.c_str(), param.second); - } - - return httpRequest; + return AWSUrlPresigner(*this).GeneratePresignedUrl(endpoint, method, customizedHeaders, expirationInSeconds, signerName, signerRegionOverride, signerServiceNameOverride); } -std::shared_ptr<Aws::Http::HttpResponse> AWSClient::MakeHttpRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const +Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, + const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const { - return m_httpClient->MakeRequest(request, m_readRateLimiter.get(), m_writeRateLimiter.get()); + return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, region, extraParams, expirationInSeconds); } - -//////////////////////////////////////////////////////////////////////////// -AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signer, errorMarshaller) +Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, const Aws::Http::URI& uri, Aws::Http::HttpMethod method, const char* region, const char* serviceName, + const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const { + return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, region, serviceName, extraParams, expirationInSeconds); } -AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signerProvider, errorMarshaller) +Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, + const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* region, + const char* serviceName, + const char* signerName, + const Aws::Http::QueryStringParameterCollection& extraParams, + long long expirationInSeconds) const { + return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, region, serviceName, signerName, extraParams, expirationInSeconds); } - -JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, - const Aws::AmazonWebServiceRequest& request, - Http::HttpMethod method, - const char* signerName, - const char* signerRegionOverride, - const char* signerServiceNameOverride) const +Aws::String AWSClient::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, const Aws::Http::URI& uri, Aws::Http::HttpMethod method, + const Aws::Http::QueryStringParameterCollection& extraParams, long long expirationInSeconds) const { - HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { - return JsonOutcome(std::move(httpOutcome)); - } - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. - return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()), - httpOutcome.GetResult()->GetHeaders(), - httpOutcome.GetResult()->GetResponseCode())); - - else - return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); + return AWSUrlPresigner(*this).GeneratePresignedUrl(request, uri, method, extraParams, expirationInSeconds); } -JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, - Http::HttpMethod method, - const char* signerName, - const char* requestName, - const char* signerRegionOverride, - const char* signerServiceNameOverride) const -{ - HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { - return JsonOutcome(std::move(httpOutcome)); - } - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - { - JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); - if (!jsonValue.WasParseSuccessful()) - { - return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false)); - } - - //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. - return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue), - httpOutcome.GetResult()->GetHeaders(), - httpOutcome.GetResult()->GetResponseCode())); +std::shared_ptr<Aws::IOStream> AWSClient::GetBodyStream(const Aws::AmazonWebServiceRequest& request) const { + if (request.GetBody() != nullptr) { + return request.GetBody(); } - - return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); + // Return an empty string stream for no body + return Aws::MakeShared<Aws::StringStream>(AWS_CLIENT_LOG_TAG, ""); } -JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const +std::shared_ptr<Aws::Http::HttpResponse> AWSClient::MakeHttpRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const { - // request is assumed to be signed - std::shared_ptr<HttpResponse> httpResponse = MakeHttpRequest(request); - - if (DoesResponseGenerateError(httpResponse)) - { - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response"); - auto error = BuildAWSError(httpResponse); - return JsonOutcome(std::move(error)); - } - - AWS_LOGSTREAM_DEBUG(AWS_CLIENT_LOG_TAG, "Request returned successful response."); - - HttpResponseOutcome httpOutcome(std::move(httpResponse)); - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - { - JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); - if (!jsonValue.WasParseSuccessful()) - { - return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false)); - } - - //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. - return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue), - httpOutcome.GetResult()->GetHeaders(), - httpOutcome.GetResult()->GetResponseCode())); - } - - return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); + return m_httpClient->MakeRequest(request, m_readRateLimiter.get(), m_writeRateLimiter.get()); } -AWSError<CoreErrors> AWSJsonClient::BuildAWSError( - const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const +void AWSClient::AppendRecursionDetectionHeader(std::shared_ptr<Aws::Http::HttpRequest> ioRequest) { - AWSError<CoreErrors> error; - if (httpResponse->HasClientError()) - { - bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; - error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); + if(!ioRequest || ioRequest->HasHeader(Aws::Http::X_AMZN_TRACE_ID_HEADER)) { + return; } - else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) - { - auto responseCode = httpResponse->GetResponseCode(); - auto errorCode = GuessBodylessErrorType(responseCode); - - Aws::StringStream ss; - ss << "No response body."; - error = AWSError<CoreErrors>(errorCode, "", ss.str(), - IsRetryableHttpResponseCode(responseCode)); - } - else - { - assert(httpResponse->GetResponseCode() != HttpResponseCode::OK); - error = GetErrorMarshaller()->Marshall(*httpResponse); + Aws::String awsLambdaFunctionName = Aws::Environment::GetEnv(AWS_LAMBDA_FUNCTION_NAME); + if(awsLambdaFunctionName.empty()) { + return; } - - error.SetResponseHeaders(httpResponse->GetHeaders()); - error.SetResponseCode(httpResponse->GetResponseCode()); - error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost()); - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error); - return error; -} - -///////////////////////////////////////////////////////////////////////////////////////// -AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signer, errorMarshaller) -{ -} - -AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, - const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, - const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : - BASECLASS(configuration, signerProvider, errorMarshaller) -{ -} - -XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, - const Aws::AmazonWebServiceRequest& request, - Http::HttpMethod method, - const char* signerName, - const char* signerRegionOverride, - const char* signerServiceNameOverride) const -{ - HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { - return XmlOutcome(std::move(httpOutcome)); + Aws::String xAmznTraceIdVal = Aws::Environment::GetEnv(X_AMZN_TRACE_ID); + if(xAmznTraceIdVal.empty()) { + return; } - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + // Escape all non-printable ASCII characters by percent encoding + Aws::OStringStream xAmznTraceIdValEncodedStr; + for(const char ch : xAmznTraceIdVal) { - XmlDocument xmlDoc = XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()); - - if (!xmlDoc.WasParseSuccessful()) + if (ch >= 0x20 && ch <= 0x7e) // ascii chars [32-126] or [' ' to '~'] are not escaped { - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, "Xml parsing for error failed with message " << xmlDoc.GetErrorMessage().c_str()); - return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Xml Parse Error", xmlDoc.GetErrorMessage(), false); + xAmznTraceIdValEncodedStr << ch; } - - return XmlOutcome(AmazonWebServiceResult<XmlDocument>(std::move(xmlDoc), - httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); - } - - return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); -} - -XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, - Http::HttpMethod method, - const char* signerName, - const char* requestName, - const char* signerRegionOverride, - const char* signerServiceNameOverride) const -{ - HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride)); - if (!httpOutcome.IsSuccess()) - { - return XmlOutcome(std::move(httpOutcome)); - } - - if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) - { - return XmlOutcome(AmazonWebServiceResult<XmlDocument>( - XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()), - httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); - } - - return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); -} - -AWSError<CoreErrors> AWSXMLClient::BuildAWSError(const std::shared_ptr<Http::HttpResponse>& httpResponse) const -{ - AWSError<CoreErrors> error; - if (httpResponse->HasClientError()) - { - bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; - error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); - } - else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) - { - auto responseCode = httpResponse->GetResponseCode(); - auto errorCode = GuessBodylessErrorType(responseCode); - - Aws::StringStream ss; - ss << "No response body."; - error = AWSError<CoreErrors>(errorCode, "", ss.str(), IsRetryableHttpResponseCode(responseCode)); - } - else - { - assert(httpResponse->GetResponseCode() != HttpResponseCode::OK); - - // When trying to build an AWS Error from a response which is an FStream, we need to rewind the - // file pointer back to the beginning in order to correctly read the input using the XML string iterator - if ((httpResponse->GetResponseBody().tellp() > 0) - && (httpResponse->GetResponseBody().tellg() > 0)) + else { - httpResponse->GetResponseBody().seekg(0); + // A percent-encoded octet is encoded as a character triplet + xAmznTraceIdValEncodedStr << '%' // consisting of the percent character "%" + << std::hex << std::setfill('0') << std::setw(2) << std::uppercase + << (size_t) ch //followed by the two hexadecimal digits representing that octet's numeric value + << std::dec << std::setfill(' ') << std::setw(0) << std::nouppercase; } - - error = GetErrorMarshaller()->Marshall(*httpResponse); } + xAmznTraceIdVal = xAmznTraceIdValEncodedStr.str(); - error.SetResponseHeaders(httpResponse->GetHeaders()); - error.SetResponseCode(httpResponse->GetResponseCode()); - error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost()); - AWS_LOGSTREAM_ERROR(AWS_CLIENT_LOG_TAG, error); - return error; + ioRequest->SetHeaderValue(Aws::Http::X_AMZN_TRACE_ID_HEADER, xAmznTraceIdVal); } diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp index f5fa676f98..a905dddb5c 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSErrorMarshaller.cpp @@ -23,6 +23,7 @@ AWS_CORE_API extern const char MESSAGE_LOWER_CASE[] = "message"; AWS_CORE_API extern const char MESSAGE_CAMEL_CASE[] = "Message"; AWS_CORE_API extern const char ERROR_TYPE_HEADER[] = "x-amzn-ErrorType"; AWS_CORE_API extern const char REQUEST_ID_HEADER[] = "x-amzn-RequestId"; +AWS_CORE_API extern const char QUERY_ERROR_HEADER[] = "x-amzn-query-error"; AWS_CORE_API extern const char TYPE[] = "__type"; AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse& httpResponse) const @@ -50,6 +51,24 @@ AWSError<CoreErrors> JsonErrorMarshaller::Marshall(const Aws::Http::HttpResponse error = FindErrorByHttpResponseCode(httpResponse.GetResponseCode()); error.SetMessage(message); } + + if (httpResponse.HasHeader(QUERY_ERROR_HEADER)) + { + auto errorCodeString = httpResponse.GetHeader(QUERY_ERROR_HEADER); + auto locationOfSemicolon = errorCodeString.find_first_of(';'); + Aws::String errorCode; + + if (locationOfSemicolon != Aws::String::npos) + { + errorCode = errorCodeString.substr(0, locationOfSemicolon); + } + else + { + errorCode = errorCodeString; + } + + error.SetExceptionName(errorCode); + } } else { diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSJsonClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSJsonClient.cpp new file mode 100644 index 0000000000..b3e19d9977 --- /dev/null +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSJsonClient.cpp @@ -0,0 +1,212 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/core/client/AWSJsonClient.h> +#include <aws/core/AmazonWebServiceRequest.h> +#include <aws/core/auth/AWSAuthSignerProvider.h> +#include <aws/core/client/AWSError.h> +#include <aws/core/client/AWSErrorMarshaller.h> +#include <aws/core/client/ClientConfiguration.h> +#include <aws/core/client/CoreErrors.h> +#include <aws/core/client/RetryStrategy.h> +#include <aws/core/http/HttpClient.h> +#include <aws/core/http/HttpResponse.h> +#include <aws/core/http/URI.h> +#include <aws/core/utils/json/JsonSerializer.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/xml/XmlSerializer.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/event/EventStream.h> +#include <aws/core/utils/UUID.h> +#include <aws/core/monitoring/MonitoringManager.h> + +#include <cassert> + + +using namespace Aws; +using namespace Aws::Client; +using namespace Aws::Http; +using namespace Aws::Utils; +using namespace Aws::Utils::Json; + +static const char AWS_JSON_CLIENT_LOG_TAG[] = "AWSJsonClient"; + +AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signer, errorMarshaller) +{ +} + +AWSJsonClient::AWSJsonClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signerProvider, errorMarshaller) +{ +} + +JsonOutcome AWSJsonClient::MakeRequest(const Aws::AmazonWebServiceRequest& request, + const Aws::Endpoint::AWSEndpoint& endpoint, + Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */, + const char* signerName /* = Aws::Auth::NULL_SIGNER */, + const char* signerRegionOverride /* = nullptr */, + const char* signerServiceNameOverride /* = nullptr */) const +{ + const Aws::Http::URI& uri = endpoint.GetURI(); + if (endpoint.GetAttributes()) { + signerName = endpoint.GetAttributes()->authScheme.GetName().c_str(); + if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningName()) { + signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str(); + } + } + return MakeRequest(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride); +} + +JsonOutcome AWSJsonClient::MakeRequest(const Aws::Endpoint::AWSEndpoint& endpoint, + Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */, + const char* signerName /* = Aws::Auth::NULL_SIGNER */, + const char* signerRegionOverride /* = nullptr */, + const char* signerServiceNameOverride /* = nullptr */) const +{ + const Aws::Http::URI& uri = endpoint.GetURI(); + if (endpoint.GetAttributes()) { + signerName = endpoint.GetAttributes()->authScheme.GetName().c_str(); + if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningName()) { + signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str(); + } + } + return MakeRequest(uri, method, signerName, signerRegionOverride, signerServiceNameOverride); +} + +JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, + const Aws::AmazonWebServiceRequest& request, + Http::HttpMethod method, + const char* signerName, + const char* signerRegionOverride, + const char* signerServiceNameOverride) const +{ + HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride)); + if (!httpOutcome.IsSuccess()) + { + return JsonOutcome(std::move(httpOutcome)); + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. + return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(httpOutcome.GetResult()->GetResponseBody()), + httpOutcome.GetResult()->GetHeaders(), + httpOutcome.GetResult()->GetResponseCode())); + + else + return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); +} + +JsonOutcome AWSJsonClient::MakeRequest(const Aws::Http::URI& uri, + Http::HttpMethod method, + const char* signerName, + const char* requestName, + const char* signerRegionOverride, + const char* signerServiceNameOverride) const +{ + HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride)); + if (!httpOutcome.IsSuccess()) + { + return JsonOutcome(std::move(httpOutcome)); + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + { + JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); + if (!jsonValue.WasParseSuccessful()) + { + return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false)); + } + + //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. + return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue), + httpOutcome.GetResult()->GetHeaders(), + httpOutcome.GetResult()->GetResponseCode())); + } + + return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); +} + +JsonOutcome AWSJsonClient::MakeEventStreamRequest(std::shared_ptr<Aws::Http::HttpRequest>& request) const +{ + // request is assumed to be signed + std::shared_ptr<HttpResponse> httpResponse = MakeHttpRequest(request); + + if (DoesResponseGenerateError(httpResponse)) + { + AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned error. Attempting to generate appropriate error codes from response"); + auto error = BuildAWSError(httpResponse); + return JsonOutcome(std::move(error)); + } + + AWS_LOGSTREAM_DEBUG(AWS_JSON_CLIENT_LOG_TAG, "Request returned successful response."); + + HttpResponseOutcome httpOutcome(std::move(httpResponse)); + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + { + JsonValue jsonValue(httpOutcome.GetResult()->GetResponseBody()); + if (!jsonValue.WasParseSuccessful()) + { + return JsonOutcome(AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Json Parser Error", jsonValue.GetErrorMessage(), false)); + } + + //this is stupid, but gcc doesn't pick up the covariant on the dereference so we have to give it a little hint. + return JsonOutcome(AmazonWebServiceResult<JsonValue>(std::move(jsonValue), + httpOutcome.GetResult()->GetHeaders(), + httpOutcome.GetResult()->GetResponseCode())); + } + + return JsonOutcome(AmazonWebServiceResult<JsonValue>(JsonValue(), httpOutcome.GetResult()->GetHeaders())); +} + +AWSError<CoreErrors> AWSJsonClient::BuildAWSError( + const std::shared_ptr<Aws::Http::HttpResponse>& httpResponse) const +{ + AWSError<CoreErrors> error; + if (httpResponse->HasClientError()) + { + bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; + error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); + } + else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) + { + auto responseCode = httpResponse->GetResponseCode(); + auto errorCode = AWSClient::GuessBodylessErrorType(responseCode); + + Aws::StringStream ss; + ss << "No response body."; + error = AWSError<CoreErrors>(errorCode, "", ss.str(), + IsRetryableHttpResponseCode(responseCode)); + } + else + { + assert(httpResponse->GetResponseCode() != HttpResponseCode::OK); + error = GetErrorMarshaller()->Marshall(*httpResponse); + } + + error.SetResponseHeaders(httpResponse->GetHeaders()); + error.SetResponseCode(httpResponse->GetResponseCode()); + error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost()); + AWS_LOGSTREAM_ERROR(AWS_JSON_CLIENT_LOG_TAG, error); + return error; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSUrlPresigner.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSUrlPresigner.cpp new file mode 100644 index 0000000000..a0bc808838 --- /dev/null +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSUrlPresigner.cpp @@ -0,0 +1,236 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/core/client/AWSUrlPresigner.h> +#include <aws/core/client/AWSClient.h> +#include <aws/core/http/HttpClientFactory.h> + +namespace Aws +{ +namespace Client +{ + +using HttpRequest = Http::HttpRequest; +using HttpMethod = Http::HttpMethod; +using URI = Http::URI; + + +AWSUrlPresigner::AWSUrlPresigner(const AWSClient& client) + : m_awsClient(client) +{} + + +Aws::Client::AWSAuthSigner* AWSUrlPresigner::GetSignerByName(const char* name) const +{ + return m_awsClient.GetSignerByName(name); +} + +std::shared_ptr<Aws::Http::HttpRequest> +ConvertToRequestForPresigning(const Aws::AmazonWebServiceRequest& request, + const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const Aws::Http::QueryStringParameterCollection& extraParams) +{ + Aws::Http::URI uriCopy = uri; + request.PutToPresignedUrl(uriCopy); + std::shared_ptr<HttpRequest> httpRequest = CreateHttpRequest(uriCopy, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); + + for (auto& param : extraParams) + { + httpRequest->AddQueryStringParameter(param.first.c_str(), param.second); + } + + return httpRequest; +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri, + HttpMethod method, + long long expirationInSeconds) const +{ + const char* regionOverride = nullptr; + const char* serviceNameOverride = nullptr; + const char* signerName = Aws::Auth::SIGV4_SIGNER; + return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri, + HttpMethod method, + const Aws::Http::HeaderValueCollection& customizedHeaders, + long long expirationInSeconds) const +{ + const char* regionOverride = nullptr; + const char* serviceNameOverride = nullptr; + const char* signerName = Aws::Auth::SIGV4_SIGNER; + return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri, + HttpMethod method, + const char* regionOverride, + long long expirationInSeconds) const +{ + const char* serviceNameOverride = nullptr; + const char* signerName = Aws::Auth::SIGV4_SIGNER; + return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const URI& uri, + HttpMethod method, + const char* regionOverride, + const Aws::Http::HeaderValueCollection& customizedHeaders, + long long expirationInSeconds) const +{ + const char* serviceNameOverride = nullptr; + const char* signerName = Aws::Auth::SIGV4_SIGNER; + return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* regionOverride, + const char* serviceNameOverride, + long long expirationInSeconds) const +{ + const char* signerName = Aws::Auth::SIGV4_SIGNER; + return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* regionOverride, + const char* serviceNameOverride, + const Aws::Http::HeaderValueCollection& customizedHeaders, + long long expirationInSeconds) const +{ + const char* signerName = Aws::Auth::SIGV4_SIGNER; + return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* regionOverride, + const char* serviceNameOverride, + const char* signerName, + long long expirationInSeconds) const +{ + const Aws::Http::HeaderValueCollection& customizedHeaders = {}; + return GeneratePresignedUrl(uri, method, regionOverride, serviceNameOverride, signerName, customizedHeaders, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* region, + const char* serviceName, + const char* signerName, + const Aws::Http::HeaderValueCollection& customizedHeaders, + long long expirationInSeconds) const +{ + /* a real method implementation */ + if (!signerName) { + signerName = Aws::Auth::SIGV4_SIGNER; + } + std::shared_ptr<HttpRequest> request = CreateHttpRequest(uri, method, Aws::Utils::Stream::DefaultResponseStreamFactoryMethod); + for (const auto& it: customizedHeaders) + { + request->SetHeaderValue(it.first.c_str(), it.second); + } + auto signer = GetSignerByName(signerName); + if (signer->PresignRequest(*request, region, serviceName, expirationInSeconds)) + { + return request->GetURIString(); + } + + return {}; +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::Endpoint::AWSEndpoint& endpoint, + Aws::Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */, + const Aws::Http::HeaderValueCollection& customizedHeaders /* = {} */, + uint64_t expirationInSeconds /* = 0 */, + const char* signerName /* = Aws::Auth::SIGV4_SIGNER */, + const char* signerRegionOverride /* = nullptr */, + const char* signerServiceNameOverride /* = nullptr */) const +{ + const Aws::Http::URI& uri = endpoint.GetURI(); + if (endpoint.GetAttributes()) { + signerName = endpoint.GetAttributes()->authScheme.GetName().c_str(); + if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningName()) { + signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str(); + } + } + + return GeneratePresignedUrl(uri, method, signerRegionOverride, signerServiceNameOverride, signerName, customizedHeaders, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, + const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* regionOverride, + const Aws::Http::QueryStringParameterCollection& extraParams, + long long expirationInSeconds) const +{ + const char* serviceNameOverride = nullptr; + const char* signerName = Aws::Auth::SIGV4_SIGNER; + + return GeneratePresignedUrl(request, uri, method, regionOverride, serviceNameOverride, signerName, extraParams, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, + const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* regionOverride, + const char* serviceNameOverride, + const char* signerName, + const Aws::Http::QueryStringParameterCollection& extraParams, + long long expirationInSeconds) const +{ + /* a real method implementation */ + if (!signerName) { + signerName = Aws::Auth::SIGV4_SIGNER; + } + std::shared_ptr<HttpRequest> httpRequest = + ConvertToRequestForPresigning(request, uri, method, extraParams); + auto signer = GetSignerByName(signerName); + if (signer->PresignRequest(*httpRequest, regionOverride, serviceNameOverride, expirationInSeconds)) + { + return httpRequest->GetURIString(); + } + + return {}; +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, + const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const char* regionOverride, + const char* serviceNameOverride, + const Aws::Http::QueryStringParameterCollection& extraParams, + long long expirationInSeconds) const +{ + const char* signerName = Aws::Auth::SIGV4_SIGNER; + return GeneratePresignedUrl(request, uri, method, regionOverride, serviceNameOverride, signerName, extraParams, expirationInSeconds); +} + +Aws::String AWSUrlPresigner::GeneratePresignedUrl(const Aws::AmazonWebServiceRequest& request, + const Aws::Http::URI& uri, + Aws::Http::HttpMethod method, + const Aws::Http::QueryStringParameterCollection& extraParams, + long long expirationInSeconds) const +{ + const char* regionOverride = nullptr; + const char* serviceNameOverride = nullptr; + const char* signerName = Aws::Auth::SIGV4_SIGNER; + + return GeneratePresignedUrl(request, uri, method, regionOverride, serviceNameOverride, signerName, extraParams, expirationInSeconds); +} + +} // namespace Client +} // namespace Aws
\ No newline at end of file diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp new file mode 100644 index 0000000000..129595b917 --- /dev/null +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AWSXmlClient.cpp @@ -0,0 +1,180 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/core/client/AWSXmlClient.h> +#include <aws/core/AmazonWebServiceRequest.h> +#include <aws/core/auth/AWSAuthSignerProvider.h> +#include <aws/core/client/AWSError.h> +#include <aws/core/client/AWSErrorMarshaller.h> +#include <aws/core/client/ClientConfiguration.h> +#include <aws/core/client/CoreErrors.h> +#include <aws/core/client/RetryStrategy.h> +#include <aws/core/http/HttpClient.h> +#include <aws/core/http/HttpResponse.h> +#include <aws/core/http/URI.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/xml/XmlSerializer.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/event/EventStream.h> +#include <aws/core/utils/UUID.h> + +using namespace Aws; +using namespace Aws::Client; +using namespace Aws::Http; +using namespace Aws::Utils; +using namespace Aws::Utils::Xml; + +static const char AWS_XML_CLIENT_LOG_TAG[] = "AWSXmlClient"; + +AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Client::AWSAuthSigner>& signer, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signer, errorMarshaller) +{ +} + +AWSXMLClient::AWSXMLClient(const Aws::Client::ClientConfiguration& configuration, + const std::shared_ptr<Aws::Auth::AWSAuthSignerProvider>& signerProvider, + const std::shared_ptr<AWSErrorMarshaller>& errorMarshaller) : + BASECLASS(configuration, signerProvider, errorMarshaller) +{ +} + +XmlOutcome AWSXMLClient::MakeRequest(const Aws::AmazonWebServiceRequest& request, + const Aws::Endpoint::AWSEndpoint& endpoint, + Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */, + const char* signerName /* = Aws::Auth::NULL_SIGNER */, + const char* signerRegionOverride /* = nullptr */, + const char* signerServiceNameOverride /* = nullptr */) const +{ + const Aws::Http::URI& uri = endpoint.GetURI(); + if (endpoint.GetAttributes()) { + signerName = endpoint.GetAttributes()->authScheme.GetName().c_str(); + if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningName()) { + signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str(); + } + } + return MakeRequest(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride); +} + +XmlOutcome AWSXMLClient::MakeRequest(const Aws::Endpoint::AWSEndpoint& endpoint, + const char* requestName /* = "" */, + Http::HttpMethod method /* = Http::HttpMethod::HTTP_POST */, + const char* signerName /* = Aws::Auth::NULL_SIGNER */, + const char* signerRegionOverride /* = nullptr */, + const char* signerServiceNameOverride /* = nullptr */) const +{ + const Aws::Http::URI& uri = endpoint.GetURI(); + if (endpoint.GetAttributes()) { + signerName = endpoint.GetAttributes()->authScheme.GetName().c_str(); + if (endpoint.GetAttributes()->authScheme.GetSigningRegion()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegion()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningRegionSet()) { + signerRegionOverride = endpoint.GetAttributes()->authScheme.GetSigningRegionSet()->c_str(); + } + if (endpoint.GetAttributes()->authScheme.GetSigningName()) { + signerServiceNameOverride = endpoint.GetAttributes()->authScheme.GetSigningName()->c_str(); + } + } + return MakeRequest(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride); +} + +XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, + const Aws::AmazonWebServiceRequest& request, + Http::HttpMethod method, + const char* signerName, + const char* signerRegionOverride, + const char* signerServiceNameOverride) const +{ + HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, request, method, signerName, signerRegionOverride, signerServiceNameOverride)); + if (!httpOutcome.IsSuccess()) + { + return XmlOutcome(std::move(httpOutcome)); + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + { + XmlDocument xmlDoc = XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()); + + if (!xmlDoc.WasParseSuccessful()) + { + AWS_LOGSTREAM_ERROR(AWS_XML_CLIENT_LOG_TAG, "Xml parsing for error failed with message " << xmlDoc.GetErrorMessage().c_str()); + return AWSError<CoreErrors>(CoreErrors::UNKNOWN, "Xml Parse Error", xmlDoc.GetErrorMessage(), false); + } + + return XmlOutcome(AmazonWebServiceResult<XmlDocument>(std::move(xmlDoc), + httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); + } + + return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); +} + +XmlOutcome AWSXMLClient::MakeRequest(const Aws::Http::URI& uri, + Http::HttpMethod method, + const char* signerName, + const char* requestName, + const char* signerRegionOverride, + const char* signerServiceNameOverride) const +{ + HttpResponseOutcome httpOutcome(BASECLASS::AttemptExhaustively(uri, method, signerName, requestName, signerRegionOverride, signerServiceNameOverride)); + if (!httpOutcome.IsSuccess()) + { + return XmlOutcome(std::move(httpOutcome)); + } + + if (httpOutcome.GetResult()->GetResponseBody().tellp() > 0) + { + return XmlOutcome(AmazonWebServiceResult<XmlDocument>( + XmlDocument::CreateFromXmlStream(httpOutcome.GetResult()->GetResponseBody()), + httpOutcome.GetResult()->GetHeaders(), httpOutcome.GetResult()->GetResponseCode())); + } + + return XmlOutcome(AmazonWebServiceResult<XmlDocument>(XmlDocument(), httpOutcome.GetResult()->GetHeaders())); +} + +AWSError<CoreErrors> AWSXMLClient::BuildAWSError(const std::shared_ptr<Http::HttpResponse>& httpResponse) const +{ + AWSError<CoreErrors> error; + if (httpResponse->HasClientError()) + { + bool retryable = httpResponse->GetClientErrorType() == CoreErrors::NETWORK_CONNECTION ? true : false; + error = AWSError<CoreErrors>(httpResponse->GetClientErrorType(), "", httpResponse->GetClientErrorMessage(), retryable); + } + else if (!httpResponse->GetResponseBody() || httpResponse->GetResponseBody().tellp() < 1) + { + auto responseCode = httpResponse->GetResponseCode(); + auto errorCode = AWSClient::GuessBodylessErrorType(responseCode); + + Aws::StringStream ss; + ss << "No response body."; + error = AWSError<CoreErrors>(errorCode, "", ss.str(), IsRetryableHttpResponseCode(responseCode)); + } + else + { + // When trying to build an AWS Error from a response which is an FStream, we need to rewind the + // file pointer back to the beginning in order to correctly read the input using the XML string iterator + if ((httpResponse->GetResponseBody().tellp() > 0) + && (httpResponse->GetResponseBody().tellg() > 0)) + { + httpResponse->GetResponseBody().seekg(0); + } + + error = GetErrorMarshaller()->Marshall(*httpResponse); + } + + error.SetResponseHeaders(httpResponse->GetHeaders()); + error.SetResponseCode(httpResponse->GetResponseCode()); + error.SetRemoteHostIpAddress(httpResponse->GetOriginatingRequest().GetResolvedRemoteHost()); + AWS_LOGSTREAM_ERROR(AWS_XML_CLIENT_LOG_TAG, error); + return error; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp new file mode 100644 index 0000000000..0907b81137 --- /dev/null +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/AdaptiveRetryStrategy.cpp @@ -0,0 +1,228 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/core/client/AdaptiveRetryStrategy.h> + +#include <aws/core/client/AWSError.h> +#include <aws/core/client/CoreErrors.h> +#include <aws/core/utils/memory/stl/AWSSet.h> + +#include <cmath> +#include <thread> + +using namespace Aws::Utils::Threading; + +namespace Aws +{ + namespace Client + { + static const double MIN_FILL_RATE = 0.5; + static const double MIN_CAPACITY = 1; + + static const double SMOOTH = 0.8; + static const double BETA = 0.7; + static const double SCALE_CONSTANT = 0.4; + + // A static list containing all service exception names classified as throttled. + static const char* THROTTLING_EXCEPTIONS[] { + "Throttling", "ThrottlingException", "ThrottledException", "RequestThrottledException", + "TooManyRequestsException", "ProvisionedThroughputExceededException", "TransactionInProgressException", + "RequestLimitExceeded", "BandwidthLimitExceeded", "LimitExceededException", "RequestThrottled", + "SlowDown", "PriorRequestNotComplete", "EC2ThrottledException"}; + static const size_t THROTTLING_EXCEPTIONS_SZ = sizeof(THROTTLING_EXCEPTIONS) / sizeof(THROTTLING_EXCEPTIONS[0]); + + + // C-tor for unit testing + RetryTokenBucket::RetryTokenBucket(double fillRate, double maxCapacity, double currentCapacity, + const Aws::Utils::DateTime& lastTimestamp, double measuredTxRate, double lastTxRateBucket, + size_t requestCount, bool enabled, double lastMaxRate, const Aws::Utils::DateTime& lastThrottleTime) + : + m_fillRate(fillRate), m_maxCapacity(maxCapacity), m_currentCapacity(currentCapacity), + m_lastTimestamp(lastTimestamp), m_measuredTxRate(measuredTxRate), + m_lastTxRateBucket(lastTxRateBucket), m_requestCount(requestCount), m_enabled(enabled), + m_lastMaxRate(lastMaxRate), m_lastThrottleTime(lastThrottleTime) + {} + + bool RetryTokenBucket::Acquire(size_t amount, bool fastFail) + { + std::lock_guard<std::recursive_mutex> locker(m_mutex); + if (!m_enabled) + { + return true; + } + Refill(); + bool notEnough = amount > m_currentCapacity; + if (notEnough && fastFail) { + return false; + } + // If all the tokens couldn't be acquired immediately, wait enough + // time to fill the remainder. + if (notEnough) { + std::chrono::duration<double> waitTime((amount - m_currentCapacity) / m_fillRate); + std::this_thread::sleep_for(waitTime); + Refill(); + } + m_currentCapacity -= amount; + return true; + } + + void RetryTokenBucket::Refill(const Aws::Utils::DateTime& now) + { + std::lock_guard<std::recursive_mutex> locker(m_mutex); + + if (0 == m_lastTimestamp.Millis()) { + m_lastTimestamp = now; + return; + } + + double fillAmount = (std::abs(now.Millis() - m_lastTimestamp.Millis()))/1000.0 * m_fillRate; + m_currentCapacity = (std::min)(m_maxCapacity, m_currentCapacity + fillAmount); + m_lastTimestamp = now; + } + + void RetryTokenBucket::UpdateRate(double newRps, const Aws::Utils::DateTime& now) + { + std::lock_guard<std::recursive_mutex> locker(m_mutex); + + Refill(now); + m_fillRate = (std::max)(newRps, MIN_FILL_RATE); + m_maxCapacity = (std::max)(newRps, MIN_CAPACITY); + m_currentCapacity = (std::min)(m_currentCapacity, m_maxCapacity); + } + + void RetryTokenBucket::UpdateMeasuredRate(const Aws::Utils::DateTime& now) + { + std::lock_guard<std::recursive_mutex> locker(m_mutex); + + double t = now.Millis() / 1000.0; + double timeBucket = floor(t * 2.0) / 2.0; + m_requestCount += 1; + if (timeBucket > m_lastTxRateBucket) { + double currentRate = m_requestCount / (timeBucket - m_lastTxRateBucket); + m_measuredTxRate = (currentRate * SMOOTH) + (m_measuredTxRate * (1 - SMOOTH)); + m_requestCount = 0; + m_lastTxRateBucket = timeBucket; + } + } + + void RetryTokenBucket::UpdateClientSendingRate(bool isThrottlingResponse, const Aws::Utils::DateTime& now) + { + std::lock_guard<std::recursive_mutex> locker(m_mutex); + + UpdateMeasuredRate(now); + + double calculatedRate = 0.0; + if (isThrottlingResponse) + { + double rateToUse = m_measuredTxRate; + if (m_enabled) + rateToUse = (std::min)(rateToUse, m_fillRate); + + m_lastMaxRate = rateToUse; + m_lastThrottleTime = now; + + calculatedRate = CUBICThrottle(rateToUse); + Enable(); + } + else + { + double timeWindow = CalculateTimeWindow(); + calculatedRate = CUBICSuccess(now, timeWindow); + } + + double newRate = (std::min)(calculatedRate, 2.0 * m_measuredTxRate); + UpdateRate(newRate, now); + } + + void RetryTokenBucket::Enable() + { + std::lock_guard<std::recursive_mutex> locker(m_mutex); + m_enabled = true; + } + + double RetryTokenBucket::CalculateTimeWindow() const + { + return pow(((m_lastMaxRate * (1.0 - BETA)) / SCALE_CONSTANT), (1.0 / 3)); + } + + double RetryTokenBucket::CUBICSuccess(const Aws::Utils::DateTime& timestamp, const double timeWindow) const + { + double dt = (timestamp.Millis() - m_lastThrottleTime.Millis()) / 1000.0; + double calculatedRate = SCALE_CONSTANT * pow(dt - timeWindow, 3.0) + m_lastMaxRate; + return calculatedRate; + } + + double RetryTokenBucket::CUBICThrottle(const double rateToUse) const + { + double calculatedRate = rateToUse * BETA; + return calculatedRate; + } + + + AdaptiveRetryStrategy::AdaptiveRetryStrategy(long maxAttempts) : + StandardRetryStrategy(maxAttempts) + {} + + AdaptiveRetryStrategy::AdaptiveRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts) : + StandardRetryStrategy(retryQuotaContainer, maxAttempts) + {} + + bool AdaptiveRetryStrategy::HasSendToken() + { + return m_retryTokenBucket.Acquire(1, m_fastFail); + } + + void AdaptiveRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome) + { + if (httpResponseOutcome.IsSuccess()) + { + m_retryQuotaContainer->ReleaseRetryQuota(Aws::Client::NO_RETRY_INCREMENT); + m_retryTokenBucket.UpdateClientSendingRate(false); + } + else + { + m_retryTokenBucket.UpdateClientSendingRate(IsThrottlingResponse(httpResponseOutcome)); + } + } + + void AdaptiveRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome, const AWSError<CoreErrors>& lastError) + { + if (httpResponseOutcome.IsSuccess()) + { + m_retryQuotaContainer->ReleaseRetryQuota(lastError); + m_retryTokenBucket.UpdateClientSendingRate(false); + } + else + { + m_retryTokenBucket.UpdateClientSendingRate(IsThrottlingResponse(httpResponseOutcome)); + } + } + + bool AdaptiveRetryStrategy::IsThrottlingResponse(const HttpResponseOutcome& httpResponseOutcome) + { + if(httpResponseOutcome.IsSuccess()) + return false; + + const AWSError<CoreErrors>& error = httpResponseOutcome.GetError(); + const Aws::Client::CoreErrors enumValue = error.GetErrorType(); + switch(enumValue) + { + case Aws::Client::CoreErrors::THROTTLING: + case Aws::Client::CoreErrors::SLOW_DOWN: + return true; + default: + break; + } + + if(std::find(THROTTLING_EXCEPTIONS, + THROTTLING_EXCEPTIONS + THROTTLING_EXCEPTIONS_SZ, error.GetExceptionName()) != THROTTLING_EXCEPTIONS + THROTTLING_EXCEPTIONS_SZ) + { + return true; + } + + return false; + } + } +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp index e517379a77..647c6e3f49 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp @@ -4,8 +4,10 @@ */ #include <aws/core/client/ClientConfiguration.h> +#include <aws/core/config/defaults/ClientConfigurationDefaults.h> #include <aws/core/auth/AWSCredentialsProvider.h> #include <aws/core/client/DefaultRetryStrategy.h> +#include <aws/core/client/AdaptiveRetryStrategy.h> #include <aws/core/platform/Environment.h> #include <aws/core/platform/OSVersionInfo.h> #include <aws/core/utils/memory/AWSMemory.h> @@ -26,43 +28,217 @@ namespace Client { static const char* CLIENT_CONFIG_TAG = "ClientConfiguration"; +static const char* USE_REQUEST_COMPRESSION_ENV_VAR = "USE_REQUEST_COMPRESSION"; +static const char* USE_REQUEST_COMPRESSION_CONFIG_VAR = "use_request_compression"; +static const char* REQUEST_MIN_COMPRESSION_SIZE_BYTES_ENV_VAR = "REQUEST_MIN_COMPRESSION_SIZE_BYTES"; +static const char* REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_VAR = "request_min_compression_size_bytes"; -AWS_CORE_API Aws::String ComputeUserAgentString() +Aws::String ComputeUserAgentString() { Aws::StringStream ss; - ss << "aws-sdk-cpp/" << Version::GetVersionString() << " " << Aws::OSVersionInfo::ComputeOSVersionString() - << " " << Version::GetCompilerVersionString(); + ss << "aws-sdk-cpp/" << Version::GetVersionString() << " " +#if defined(AWS_USER_AGENT_CUSTOMIZATION) +#define XSTR(V) STR(V) +#define STR(V) #V + << XSTR(AWS_USER_AGENT_CUSTOMIZATION) << " " +#undef STR +#undef XSTR +#endif + << Aws::OSVersionInfo::ComputeOSVersionString() << " " + << Version::GetCompilerVersionString(); return ss.str(); } -ClientConfiguration::ClientConfiguration() : - scheme(Aws::Http::Scheme::HTTPS), - useDualStack(false), - maxConnections(25), - httpRequestTimeoutMs(0), - requestTimeoutMs(3000), - connectTimeoutMs(1000), - enableTcpKeepAlive(true), - tcpKeepAliveIntervalMs(30000), - lowSpeedLimit(1), - proxyScheme(Aws::Http::Scheme::HTTP), - proxyPort(0), - executor(Aws::MakeShared<Aws::Utils::Threading::DefaultExecutor>(CLIENT_CONFIG_TAG)), - verifySSL(true), - writeRateLimiter(nullptr), - readRateLimiter(nullptr), - httpLibOverride(Aws::Http::TransferLibType::DEFAULT_CLIENT), - followRedirects(FollowRedirectsPolicy::DEFAULT), - disableExpectHeader(false), - enableClockSkewAdjustment(true), - enableHostPrefixInjection(true), - enableEndpointDiscovery(false), - profileName(Aws::Auth::GetConfigProfileName()) +void setLegacyClientConfigurationParameters(ClientConfiguration& clientConfig) { - AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use SDK Auto Resolved profile: [" << profileName << "] if not specified by users."); + clientConfig.scheme = Aws::Http::Scheme::HTTPS; + clientConfig.useDualStack = false; + clientConfig.useFIPS = false; + clientConfig.maxConnections = 25; + clientConfig.httpRequestTimeoutMs = 0; + clientConfig.requestTimeoutMs = 3000; + clientConfig.connectTimeoutMs = 1000; + clientConfig.enableTcpKeepAlive = true; + clientConfig.tcpKeepAliveIntervalMs = 30000; + clientConfig.lowSpeedLimit = 1; + clientConfig.proxyScheme = Aws::Http::Scheme::HTTP; + clientConfig.proxyPort = 0; + clientConfig.executor = Aws::MakeShared<Aws::Utils::Threading::DefaultExecutor>(CLIENT_CONFIG_TAG); + clientConfig.verifySSL = true; + clientConfig.writeRateLimiter = nullptr; + clientConfig.readRateLimiter = nullptr; + clientConfig.httpLibOverride = Aws::Http::TransferLibType::DEFAULT_CLIENT; + clientConfig.followRedirects = FollowRedirectsPolicy::DEFAULT; + clientConfig.disableExpectHeader = false; + clientConfig.enableClockSkewAdjustment = true; + clientConfig.enableHostPrefixInjection = true; + clientConfig.profileName = Aws::Auth::GetConfigProfileName(); - // Initialize Retry Strategy - int maxAttempts; + Aws::String useCompressionConfig = clientConfig.LoadConfigFromEnvOrProfile( + USE_REQUEST_COMPRESSION_ENV_VAR, + Aws::Auth::GetConfigProfileName(), + USE_REQUEST_COMPRESSION_CONFIG_VAR, + {"ENABLE", "DISABLE", "enable", "disable"}, + "ENABLE" + ); + + if (Aws::Utils::StringUtils::ToLower(useCompressionConfig.c_str()) == "disable") { + clientConfig.requestCompressionConfig.useRequestCompression = Aws::Client::UseRequestCompression::DISABLE; + AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Request Compression disabled"); + } else { + //Using default to true for forward compatibility in case new config is added but SDK is not updated. + clientConfig.requestCompressionConfig.useRequestCompression = Aws::Client::UseRequestCompression::ENABLE; + AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Request Compression enabled"); + } + + // Getting min request compression length + Aws::String minRequestCompressionString = Aws::Environment::GetEnv(REQUEST_MIN_COMPRESSION_SIZE_BYTES_ENV_VAR); + if (minRequestCompressionString.empty()) + { + minRequestCompressionString = Aws::Config::GetCachedConfigValue(REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_VAR); + } + if (!minRequestCompressionString.empty()) { + clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes = static_cast<int>(Aws::Utils::StringUtils::ConvertToInt32(minRequestCompressionString.c_str())); + if (clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes > 10485760) { + AWS_LOGSTREAM_ERROR(CLIENT_CONFIG_TAG, "ClientConfiguration for MinReqCompression is unsupported, received: " << clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes); + } + } + AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use MinReqCompression: " << clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes); + + AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use SDK Auto Resolved profile: [" << clientConfig.profileName << "] if not specified by users."); + + // Automatically determine the AWS region from environment variables, configuration file and EC2 metadata. + clientConfig.region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION"); + if (!clientConfig.region.empty()) + { + return; + } + + clientConfig.region = Aws::Environment::GetEnv("AWS_REGION"); + if (!clientConfig.region.empty()) + { + return; + } + + clientConfig.region = Aws::Config::GetCachedConfigValue("region"); + if (!clientConfig.region.empty()) + { + return; + } + + // Set the endpoint to interact with EC2 instance's metadata service + Aws::String ec2MetadataServiceEndpoint = Aws::Environment::GetEnv("AWS_EC2_METADATA_SERVICE_ENDPOINT"); + if (! ec2MetadataServiceEndpoint.empty()) + { + //By default we use the IPv4 default metadata service address + auto client = Aws::Internal::GetEC2MetadataClient(); + if (client != nullptr) + { + client->SetEndpoint(ec2MetadataServiceEndpoint); + } + } +} + +ClientConfiguration::ClientConfiguration() +{ + this->disableIMDS = false; + setLegacyClientConfigurationParameters(*this); + retryStrategy = InitRetryStrategy(); + + if (!this->disableIMDS && + region.empty() && + Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true") + { + auto client = Aws::Internal::GetEC2MetadataClient(); + if (client) + { + region = client->GetCurrentRegion(); + } + } + if (!region.empty()) + { + return; + } + region = Aws::String(Aws::Region::US_EAST_1); +} + +ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisableIMDS) +{ + this->disableIMDS = shouldDisableIMDS; + setLegacyClientConfigurationParameters(*this); + // Call EC2 Instance Metadata service only once + Aws::String ec2MetadataRegion; + bool hasEc2MetadataRegion = false; + if (!this->disableIMDS && + region.empty() && + Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true") { + auto client = Aws::Internal::GetEC2MetadataClient(); + if (client) + { + ec2MetadataRegion = client->GetCurrentRegion(); + hasEc2MetadataRegion = true; + region = ec2MetadataRegion; + } + } + + if(region.empty()) + { + region = Aws::String(Aws::Region::US_EAST_1); + } + + if (profile && Aws::Config::HasCachedConfigProfile(profile)) { + this->profileName = Aws::String(profile); + AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, + "Use user specified profile: [" << this->profileName << "] for ClientConfiguration."); + auto tmpRegion = Aws::Config::GetCachedConfigProfile(this->profileName).GetRegion(); + if (!tmpRegion.empty()) { + region = tmpRegion; + } + + Aws::String profileDefaultsMode = Aws::Config::GetCachedConfigProfile(this->profileName).GetDefaultsMode(); + Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, profileDefaultsMode, + hasEc2MetadataRegion, ec2MetadataRegion); + return; + } + if (!retryStrategy) + { + retryStrategy = InitRetryStrategy(); + } + + AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "User specified profile: [" << profile << "] is not found, will use the SDK resolved one."); +} + +ClientConfiguration::ClientConfiguration(bool /*useSmartDefaults*/, const char* defaultMode, bool shouldDisableIMDS) +{ + this->disableIMDS = shouldDisableIMDS; + setLegacyClientConfigurationParameters(*this); + + // Call EC2 Instance Metadata service only once + Aws::String ec2MetadataRegion; + bool hasEc2MetadataRegion = false; + if (!this->disableIMDS && + region.empty() && + Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true") + { + auto client = Aws::Internal::GetEC2MetadataClient(); + if (client) + { + ec2MetadataRegion = client->GetCurrentRegion(); + hasEc2MetadataRegion = true; + region = ec2MetadataRegion; + } + } + if (region.empty()) + { + region = Aws::String(Aws::Region::US_EAST_1); + } + + Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, defaultMode, hasEc2MetadataRegion, ec2MetadataRegion); +} + +std::shared_ptr<RetryStrategy> InitRetryStrategy(Aws::String retryMode) +{ + int maxAttempts = 0; Aws::String maxAttemptsString = Aws::Environment::GetEnv("AWS_MAX_ATTEMPTS"); if (maxAttemptsString.empty()) { @@ -83,15 +259,21 @@ ClientConfiguration::ClientConfiguration() : } } - Aws::String retryMode = Aws::Environment::GetEnv("AWS_RETRY_MODE"); + if (retryMode.empty()) + { + retryMode = Aws::Environment::GetEnv("AWS_RETRY_MODE"); + } if (retryMode.empty()) { retryMode = Aws::Config::GetCachedConfigValue("retry_mode"); } + + std::shared_ptr<RetryStrategy> retryStrategy; if (retryMode == "standard") { if (maxAttempts < 0) { + // negative value set above force usage of default max attempts retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG); } else @@ -99,61 +281,55 @@ ClientConfiguration::ClientConfiguration() : retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG, maxAttempts); } } - else - { - retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(CLIENT_CONFIG_TAG); - } - - // Automatically determine the AWS region from environment variables, configuration file and EC2 metadata. - region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION"); - if (!region.empty()) - { - return; - } - - region = Aws::Environment::GetEnv("AWS_REGION"); - if (!region.empty()) + else if (retryMode == "adaptive") { - return; - } - - region = Aws::Config::GetCachedConfigValue("region"); - if (!region.empty()) - { - return; - } - - if (Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true") - { - auto client = Aws::Internal::GetEC2MetadataClient(); - if (client) + if (maxAttempts < 0) { - region = client->GetCurrentRegion(); + // negative value set above force usage of default max attempts + retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG); + } + else + { + retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG, maxAttempts); } } - - if (!region.empty()) + else { - return; + retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(CLIENT_CONFIG_TAG); } - region = Aws::String(Aws::Region::US_EAST_1); + return retryStrategy; } -ClientConfiguration::ClientConfiguration(const char* profile) : ClientConfiguration() +Aws::String ClientConfiguration::LoadConfigFromEnvOrProfile(const Aws::String& envKey, + const Aws::String& profile, + const Aws::String& profileProperty, + const Aws::Vector<Aws::String>& allowedValues, + const Aws::String& defaultValue) { - if (profile && Aws::Config::HasCachedConfigProfile(profile)) - { - this->profileName = Aws::String(profile); - AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Use user specified profile: [" << this->profileName << "] for ClientConfiguration."); - auto tmpRegion = Aws::Config::GetCachedConfigProfile(this->profileName).GetRegion(); - if (!tmpRegion.empty()) - { - region = tmpRegion; + Aws::String option = Aws::Environment::GetEnv(envKey.c_str()); + if (option.empty()) { + option = Aws::Config::GetCachedConfigValue(profile, profileProperty); + } + option = Aws::Utils::StringUtils::ToLower(option.c_str()); + if (option.empty()) { + return defaultValue; + } + + if (!allowedValues.empty() && std::find(allowedValues.cbegin(), allowedValues.cend(), option) == allowedValues.cend()) { + Aws::OStringStream expectedStr; + expectedStr << "["; + for(const auto& allowed : allowedValues) { + expectedStr << allowed << ";"; } - return; + expectedStr << "]"; + + AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "Unrecognised value for " << envKey << ": " << option << + ". Using default instead: " << defaultValue << + ". Expected empty or one of: " << expectedStr.str()); + option = defaultValue; } - AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "User specified profile: [" << profile << "] is not found, will use the SDK resolved one."); + return option; } } // namespace Client diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp index 8c2c288dcd..50a7f9308d 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/CoreErrors.cpp @@ -18,7 +18,8 @@ using namespace Aws::Http; #pragma warning(disable : 4592) #endif -static Aws::UniquePtr<Aws::Map<Aws::String, AWSError<CoreErrors> > > s_CoreErrorsMapper(nullptr); +using ErrorsMapperContainer = Aws::Map<Aws::String, AWSError<CoreErrors> >; +static ErrorsMapperContainer* s_CoreErrorsMapper(nullptr); #ifdef _MSC_VER #pragma warning(pop) @@ -30,7 +31,7 @@ void CoreErrorsMapper::InitCoreErrorsMapper() { return; } - s_CoreErrorsMapper = Aws::MakeUnique<Aws::Map<Aws::String, AWSError<CoreErrors> > >("InitCoreErrorsMapper"); + s_CoreErrorsMapper = Aws::New<ErrorsMapperContainer>("InitCoreErrorsMapper"); s_CoreErrorsMapper->emplace("IncompleteSignature", AWSError<CoreErrors>(CoreErrors::INCOMPLETE_SIGNATURE, false)); s_CoreErrorsMapper->emplace("IncompleteSignatureException", AWSError<CoreErrors>(CoreErrors::INCOMPLETE_SIGNATURE, false)); @@ -92,10 +93,8 @@ void CoreErrorsMapper::InitCoreErrorsMapper() void CoreErrorsMapper::CleanupCoreErrorsMapper() { - if (s_CoreErrorsMapper) - { - s_CoreErrorsMapper = nullptr; - } + Aws::Delete(s_CoreErrorsMapper); + s_CoreErrorsMapper = nullptr; } AWSError<CoreErrors> CoreErrorsMapper::GetErrorForName(const char* errorName) @@ -149,3 +148,12 @@ AWS_CORE_API AWSError<CoreErrors> CoreErrorsMapper::GetErrorForHttpResponseCode( error.SetResponseCode(code); return error; } + +/** + * Overload ostream operator<< for CoreErrors enum class for a prettier output such as "103" and not "<67-00 00-00>" + */ +Aws::OStream& Aws::Client::operator<< (Aws::OStream& oStream, CoreErrors code) +{ + oStream << Aws::Utils::StringUtils::to_string(static_cast<typename std::underlying_type<HttpResponseCode>::type>(code)); + return oStream; +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp index 7e57c79ffc..405d7566cf 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/DefaultRetryStrategy.cpp @@ -28,5 +28,5 @@ long DefaultRetryStrategy::CalculateDelayBeforeNextRetry(const AWSError<CoreErro return 0; } - return (1 << attemptedRetries) * m_scaleFactor; + return (1UL << attemptedRetries) * m_scaleFactor; } diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/GenericClientConfiguration.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/GenericClientConfiguration.cpp new file mode 100644 index 0000000000..f0a4e91d5b --- /dev/null +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/GenericClientConfiguration.cpp @@ -0,0 +1,103 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/core/client/GenericClientConfiguration.h> +#include <aws/core/platform/Environment.h> +#include <aws/core/utils/memory/AWSMemory.h> +#include <aws/core/utils/threading/Executor.h> + + +namespace Aws +{ +namespace Client +{ +template struct AWS_CORE_API GenericClientConfiguration<false>; + +bool IsEndpointDiscoveryEnabled(const Aws::String& endpointOverride, const Aws::String &profileName) +{ + bool enabled = true; // default value for AWS Services with enabled discovery trait + if (!endpointOverride.empty()) + { + enabled = false; + } + else + { + static const char* AWS_ENABLE_ENDPOINT_DISCOVERY_ENV_KEY = "AWS_ENABLE_ENDPOINT_DISCOVERY"; + static const char* AWS_ENABLE_ENDPOINT_DISCOVERY_PROFILE_KEY = "AWS_ENABLE_ENDPOINT_DISCOVERY"; + static const char* AWS_ENABLE_ENDPOINT_ENABLED = "true"; + static const char* AWS_ENABLE_ENDPOINT_DISABLED = "false"; + + Aws::String enableEndpointDiscovery = ClientConfiguration::LoadConfigFromEnvOrProfile(AWS_ENABLE_ENDPOINT_DISCOVERY_ENV_KEY, + profileName, + AWS_ENABLE_ENDPOINT_DISCOVERY_PROFILE_KEY, + {AWS_ENABLE_ENDPOINT_ENABLED, AWS_ENABLE_ENDPOINT_DISABLED}, + AWS_ENABLE_ENDPOINT_ENABLED); + + if (AWS_ENABLE_ENDPOINT_DISABLED == enableEndpointDiscovery) + { + // enabled by default unless explicitly disabled in ENV, profile config file, or programmatically later + enabled = false; + } + } + return enabled; +} + +GenericClientConfiguration<true>::GenericClientConfiguration() + : ClientConfiguration(), + enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection), + enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery) +{ + enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName); + enableHostPrefixInjection = false; // disabled by default in the SDK +} + +GenericClientConfiguration<true>::GenericClientConfiguration(const char* inputProfileName, bool shouldDisableIMDS) + : ClientConfiguration(inputProfileName, shouldDisableIMDS), + enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection), + enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery) +{ + enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName); + enableHostPrefixInjection = false; // disabled by default in the SDK +} + +GenericClientConfiguration<true>::GenericClientConfiguration(bool useSmartDefaults, const char* inputDefaultMode, bool shouldDisableIMDS) + : ClientConfiguration(useSmartDefaults, inputDefaultMode, shouldDisableIMDS), + enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection), + enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery) +{ + enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName); + enableHostPrefixInjection = false; // disabled by default in the SDK +} + +GenericClientConfiguration<true>::GenericClientConfiguration(const ClientConfiguration& config) + : ClientConfiguration(config), + enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection), + enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery) +{ + enableEndpointDiscovery = IsEndpointDiscoveryEnabled(this->endpointOverride, this->profileName); + enableHostPrefixInjection = false; // disabled by default in the SDK +} + +GenericClientConfiguration<true>::GenericClientConfiguration(const GenericClientConfiguration<true>& other) + : ClientConfiguration(static_cast<ClientConfiguration>(other)), + enableHostPrefixInjection(ClientConfiguration::enableHostPrefixInjection), + enableEndpointDiscovery(ClientConfiguration::enableEndpointDiscovery) +{ + if (other.enableEndpointDiscovery) { + enableEndpointDiscovery = other.enableEndpointDiscovery.value(); + } + enableHostPrefixInjection = other.enableHostPrefixInjection; +} + +GenericClientConfiguration<true>& GenericClientConfiguration<true>::operator=(const GenericClientConfiguration<true>& other) +{ + if (this != &other) { + *static_cast<ClientConfiguration*>(this) = static_cast<ClientConfiguration>(other); + } + return *this; +} + +} // namespace Client +} // namespace Aws diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RequestCompression.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RequestCompression.cpp new file mode 100644 index 0000000000..e51a49049b --- /dev/null +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RequestCompression.cpp @@ -0,0 +1,336 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/core/client/RequestCompression.h> +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/memory/AWSMemory.h> +#include <algorithm> +#include <aws/core/utils/memory/stl/AWSAllocator.h> + +#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION +#include "zlib.h" + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +#include <fcntl.h> +#include <io.h> +#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +#define SET_BINARY_MODE(file) +#endif // defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +// Defining zlib chunks to be 256k +static const size_t ZLIB_CHUNK=263144; +static const char AWS_REQUEST_COMPRESSION_ALLOCATION_TAG[] = + "RequestCompressionAlloc"; +#endif // ENABLED_ZLIB_REQUEST_COMPRESSION + +static const char AWS_REQUEST_COMPRESSION_LOG_TAG[] = "RequestCompression"; + +Aws::String Aws::Client::GetCompressionAlgorithmId(const CompressionAlgorithm &algorithm) +{ + switch (algorithm) + { + case CompressionAlgorithm::GZIP: + return "gzip"; + default: + return ""; + } +} + +#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION +#ifdef USE_AWS_MEMORY_MANAGEMENT +static const char* ZlibMemTag = "zlib"; +static const size_t offset = sizeof(size_t); // to make space for size of the array +//Define custom memory allocation for zlib +// if fail to allocate, return Z_NULL +void* aws_zalloc(void * /* opaque */, unsigned items, unsigned size) +{ + unsigned sizeToAllocate = items*size; + size_t sizeToAllocateWithOffset = sizeToAllocate + offset; + if ((size != 0 && sizeToAllocate / size != items) + || (sizeToAllocateWithOffset <= sizeToAllocate )) + { + return Z_NULL; + } + char* newMem = reinterpret_cast<char*>(Aws::Malloc(ZlibMemTag, sizeToAllocateWithOffset)); + if (newMem != nullptr) { + std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem); + *pointerToSize = size; + return reinterpret_cast<void*>(newMem + offset); + } + else + { + return Z_NULL; + } +} + +void aws_zfree(void * /* opaque */, void * ptr) +{ + if(ptr) + { + char* shiftedMemory = reinterpret_cast<char*>(ptr); + Aws::Free(shiftedMemory - offset); + } +} + +#endif // AWS_CUSTOM_MEMORY_MANAGEMENT +#endif // ENABLED_ZLIB_REQUEST_COMPRESSION + + +iostream_outcome Aws::Client::RequestCompression::compress(std::shared_ptr<Aws::IOStream> input, + const CompressionAlgorithm &algorithm) const +{ +#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION + if (algorithm == CompressionAlgorithm::GZIP) + { + // calculating stream size + input->seekg(0, input->end); + size_t streamSize = input->tellg(); + input->seekg(0, input->beg); + + AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressing request of " << streamSize << " bytes."); + + // Preparing output + std::shared_ptr<Aws::IOStream> output = Aws::MakeShared<Aws::StringStream>(AWS_REQUEST_COMPRESSION_ALLOCATION_TAG); + if(!output) + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate output while compressing") + return false; + } + // Prepare ZLIB to compress + int ret = Z_NULL; + int flush = Z_NO_FLUSH; + z_stream strm = {}; + auto in = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG); + if(!in) + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate in buffer while compressing") + return false; + } + + auto out = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG); + if(!out) + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate out buffer while compressing") + return false; + } + + //Preparing allocators +#ifdef USE_AWS_MEMORY_MANAGEMENT + strm.zalloc = (void *(*)(void *, unsigned, unsigned)) aws_zalloc; + strm.zfree = (void (*)(void *, void *)) aws_zfree; +#else + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; +#endif + strm.opaque = Z_NULL; + + const int MAX_WINDOW_GZIP = 31; + const int DEFAULT_MEM_LEVEL_USAGE = 8; + ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WINDOW_GZIP, DEFAULT_MEM_LEVEL_USAGE, Z_DEFAULT_STRATEGY); + if(ret != Z_OK) + { + return false; + } + + //Adding one to the stream size counter to account for the EOF marker. + streamSize++; + size_t toRead; + // Compress + do { + toRead = std::min(streamSize, ZLIB_CHUNK); + // Fill the buffer + if (! input->read(reinterpret_cast<char *>(in.get()), toRead)) + { + if (input->eof()) + { + //Last read need flush when exit loop + flush = Z_FINISH; + } + else { + AWS_LOGSTREAM_ERROR( + AWS_REQUEST_COMPRESSION_LOG_TAG, + "Uncompress request failed to read from stream"); + return false; + } + } + streamSize -= toRead; //left to read + strm.avail_in = (flush == Z_FINISH)?toRead-1:toRead; //skip EOF if included + strm.next_in = in.get(); + do + { + // Run deflate on buffers + strm.avail_out = ZLIB_CHUNK; + strm.next_out = out.get(); + + ret = deflate(&strm, flush); + + // writing the output + assert(ZLIB_CHUNK >= strm.avail_out); + unsigned output_size = ZLIB_CHUNK - strm.avail_out; + if(! output->write(reinterpret_cast<char *>(out.get()), output_size)) + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to write to output stream"); + return false; + } + } while (strm.avail_out == 0); + assert(strm.avail_in == 0); // All data was read + } while (flush != Z_FINISH); + assert(ret == Z_STREAM_END); // Completed stream + AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request to: " << strm.total_out << " bytes"); + deflateEnd(&strm); + return output; + } + else + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm)); + return false; + } +#else + // If there is no support to compress, always fail calls to this method. + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm)); + AWS_UNREFERENCED_PARAM(input); // silencing warning; + return false; +#endif +} + +Aws::Utils::Outcome<std::shared_ptr<Aws::IOStream>, bool> +Aws::Client::RequestCompression::uncompress(std::shared_ptr<Aws::IOStream> input, const CompressionAlgorithm &algorithm) const +{ +#ifdef ENABLED_ZLIB_REQUEST_COMPRESSION + if (algorithm == CompressionAlgorithm::GZIP) + { + // calculating stream size + input->seekg(0, input->end); + size_t streamSize = input->tellg(); + input->seekg(0, input->beg); + + AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompressing request of " << streamSize << " bytes."); + + // Preparing output + std::shared_ptr<Aws::IOStream> output = Aws::MakeShared<Aws::StringStream>( AWS_REQUEST_COMPRESSION_ALLOCATION_TAG); + if(!output) + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate output while uncompressing") + return false; + } + + // Prepare ZLIB to uncompress + int ret = Z_NULL; + z_stream strm = {}; + auto in = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG); + if(!in) + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate in buffer while uncompressing") + return false; + } + + auto out = Aws::MakeUniqueArray<unsigned char>(ZLIB_CHUNK, AWS_REQUEST_COMPRESSION_ALLOCATION_TAG); + if(!out) + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to allocate out buffer while uncompressing") + return false; + } + + //preparing allocation +#ifdef USE_AWS_MEMORY_MANAGEMENT + strm.zalloc = (void *(*)(void *, unsigned, unsigned)) aws_zalloc; + strm.zfree = (void (*)(void *, void *)) aws_zfree; +#else + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; +#endif + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + + const int MAX_WINDOW_GZIP = 31; + ret = inflateInit2(&strm, MAX_WINDOW_GZIP); + if (ret != Z_OK) + { + return false; + } + + //Adding one to the stream size counter to account for the EOF marker. + streamSize++; + size_t toRead; + // Decompress + do { + toRead = (streamSize < ZLIB_CHUNK)?streamSize:ZLIB_CHUNK; + if (toRead < 1) break; // Nothing left to read + // Fill the buffer + if(! input->read(reinterpret_cast<char *>(in.get()), toRead)) + { + if (input->eof()) + { + //skip passing the EOF to the buffer + toRead--; + } + else + { + AWS_LOGSTREAM_ERROR( + AWS_REQUEST_COMPRESSION_LOG_TAG, + "Compress request failed to read from stream"); + return false; + } + } + + // Filling input buffer to decompress + strm.avail_in = toRead; + strm.next_in = in.get(); + do + { + // Run inflate on buffers + strm.avail_out = ZLIB_CHUNK; + strm.next_out = out.get(); + + ret = inflate(&strm, Z_NO_FLUSH); + // Catch errors + switch (ret) + { + case Z_NEED_DICT: + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to inflate with code: Z_NEED_DICT"); + return false; + case Z_DATA_ERROR: + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to inflate with code: Z_DATA_ERROR"); + return false; + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Compressed request failed to inflate with code: Z_MEM_ERROR"); + return false; + } + + // writing the output + unsigned output_size = ZLIB_CHUNK - strm.avail_out; + if(! output->write(reinterpret_cast<char *>(out.get()), output_size)) { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompressed request failed to write to output stream"); + return false; + } + } while (strm.avail_out == 0); + } while (ret != Z_STREAM_END); + // clean up + (void)inflateEnd(&strm); + if (ret == Z_STREAM_END) + { + AWS_LOGSTREAM_TRACE(AWS_REQUEST_COMPRESSION_LOG_TAG, "Decompressed request to: " << strm.total_out << " bytes"); + return output; + } + else + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Failed to decompress after read input completely"); + return false; + } + } + else + { + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm)); + return false; + } +#else + // If there is no support to compress, always fail calls to this method. + AWS_LOGSTREAM_ERROR(AWS_REQUEST_COMPRESSION_LOG_TAG, "Uncompress request requested in runtime without support: " << GetCompressionAlgorithmId(algorithm)); + AWS_UNREFERENCED_PARAM(input); // silencing warning; + return false; +#endif +} diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp index b439b7ca99..77b6f5abbb 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/RetryStrategy.cpp @@ -17,18 +17,21 @@ namespace Aws { static const int INITIAL_RETRY_TOKENS = 500; static const int RETRY_COST = 5; - static const int NO_RETRY_INCREMENT = 1; static const int TIMEOUT_RETRY_COST = 10; StandardRetryStrategy::StandardRetryStrategy(long maxAttempts) : m_retryQuotaContainer(Aws::MakeShared<DefaultRetryQuotaContainer>("StandardRetryStrategy")), m_maxAttempts(maxAttempts) - {} + { + srand((unsigned int)time(NULL)); + } StandardRetryStrategy::StandardRetryStrategy(std::shared_ptr<RetryQuotaContainer> retryQuotaContainer, long maxAttempts) : m_retryQuotaContainer(retryQuotaContainer), m_maxAttempts(maxAttempts) - {} + { + srand((unsigned int)time(NULL)); + } void StandardRetryStrategy::RequestBookkeeping(const HttpResponseOutcome& httpResponseOutcome) { @@ -60,7 +63,8 @@ namespace Aws long StandardRetryStrategy::CalculateDelayBeforeNextRetry(const AWSError<CoreErrors>& error, long attemptedRetries) const { AWS_UNREFERENCED_PARAM(error); - return (std::min)(rand() % 1000 * (1 << attemptedRetries), 20000); + // Maximum left shift factor is capped by ceil(log2(max_delay)), to avoid wrap-around and overflow into negative values: + return (std::min)(rand() % 1000 * (1 << (std::min)(attemptedRetries, 15L)), 20000); } DefaultRetryQuotaContainer::DefaultRetryQuotaContainer() : m_retryQuota(INITIAL_RETRY_TOKENS) @@ -99,4 +103,4 @@ namespace Aws ReleaseRetryQuota(capacityAmount); } } -}
\ No newline at end of file +} |