aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http')
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp49
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp203
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp40
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp42
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp54
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp510
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp153
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp730
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp104
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp46
10 files changed, 1931 insertions, 0 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp
new file mode 100644
index 0000000000..8542023393
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClient.cpp
@@ -0,0 +1,49 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/HttpClient.h>
+#include <aws/core/http/HttpRequest.h>
+
+using namespace Aws;
+using namespace Aws::Http;
+
+HttpClient::HttpClient() :
+ m_disableRequestProcessing( false ),
+ m_requestProcessingSignalLock(),
+ m_requestProcessingSignal()
+{
+}
+
+void HttpClient::DisableRequestProcessing()
+{
+ m_disableRequestProcessing = true;
+ m_requestProcessingSignal.notify_all();
+}
+
+void HttpClient::EnableRequestProcessing()
+{
+ m_disableRequestProcessing = false;
+}
+
+bool HttpClient::IsRequestProcessingEnabled() const
+{
+ return m_disableRequestProcessing.load() == false;
+}
+
+void HttpClient::RetryRequestSleep(std::chrono::milliseconds sleepTime)
+{
+ std::unique_lock< std::mutex > signalLocker(m_requestProcessingSignalLock);
+ m_requestProcessingSignal.wait_for(signalLocker, sleepTime, [this](){ return m_disableRequestProcessing.load() == true; });
+}
+
+bool HttpClient::ContinueRequest(const Aws::Http::HttpRequest& request) const
+{
+ if (request.GetContinueRequestHandler())
+ {
+ return request.GetContinueRequestHandler()(&request);
+ }
+
+ return true;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp
new file mode 100644
index 0000000000..a556e39a5d
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp
@@ -0,0 +1,203 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/HttpClientFactory.h>
+
+#if ENABLE_CURL_CLIENT
+#include <aws/core/http/curl/CurlHttpClient.h>
+#include <signal.h>
+
+#elif ENABLE_WINDOWS_CLIENT
+#include <aws/core/client/ClientConfiguration.h>
+#if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT
+#error #include <aws/core/http/windows/IXmlHttpRequest2HttpClient.h>
+#if BYPASS_DEFAULT_PROXY
+#error #include <aws/core/http/windows/WinHttpSyncHttpClient.h>
+#endif
+#else
+#error #include <aws/core/http/windows/WinINetSyncHttpClient.h>
+#error #include <aws/core/http/windows/WinHttpSyncHttpClient.h>
+#endif
+#endif
+
+#include <aws/core/http/standard/StandardHttpRequest.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <cassert>
+
+using namespace Aws::Client;
+using namespace Aws::Http;
+using namespace Aws::Utils::Logging;
+
+namespace Aws
+{
+ namespace Http
+ {
+ static std::shared_ptr<HttpClientFactory>& GetHttpClientFactory()
+ {
+ static std::shared_ptr<HttpClientFactory> s_HttpClientFactory(nullptr);
+ return s_HttpClientFactory;
+ }
+ static bool s_InitCleanupCurlFlag(false);
+ static bool s_InstallSigPipeHandler(false);
+
+ static const char* HTTP_CLIENT_FACTORY_ALLOCATION_TAG = "HttpClientFactory";
+
+#if ENABLE_CURL_CLIENT && !defined(_WIN32)
+ static void LogAndSwallowHandler(int signal)
+ {
+ switch(signal)
+ {
+ case SIGPIPE:
+ AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Received a SIGPIPE error");
+ break;
+ default:
+ AWS_LOGSTREAM_ERROR(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Unhandled system SIGNAL error" << signal);
+ }
+ }
+#endif
+
+ class DefaultHttpClientFactory : public HttpClientFactory
+ {
+ std::shared_ptr<HttpClient> CreateHttpClient(const ClientConfiguration& clientConfiguration) const override
+ {
+ // Figure out whether the selected option is available but fail gracefully and return a default of some type if not
+ // Windows clients: Http and Inet are always options, Curl MIGHT be an option if USE_CURL_CLIENT is on, and http is "default"
+ // Other clients: Curl is your default
+#if ENABLE_WINDOWS_CLIENT
+#if ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT
+#if BYPASS_DEFAULT_PROXY
+ switch (clientConfiguration.httpLibOverride)
+ {
+ case TransferLibType::WIN_HTTP_CLIENT:
+ AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating WinHTTP http client.");
+ return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration);
+ case TransferLibType::WIN_INET_CLIENT:
+ AWS_LOGSTREAM_WARN(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "WinINet http client is not supported with the current build configuration.");
+ // fall-through
+ default:
+ AWS_LOGSTREAM_INFO(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "Creating IXMLHttpRequest http client.");
+ return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration);
+ }
+#else
+ return Aws::MakeShared<IXmlHttpRequest2HttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration);
+#endif // BYPASS_DEFAULT_PROXY
+#else
+ switch (clientConfiguration.httpLibOverride)
+ {
+ case TransferLibType::WIN_INET_CLIENT:
+ return Aws::MakeShared<WinINetSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration);
+
+ default:
+ return Aws::MakeShared<WinHttpSyncHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration);
+ }
+#endif // ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT
+#elif ENABLE_CURL_CLIENT
+ return Aws::MakeShared<CurlHttpClient>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, clientConfiguration);
+#else
+ // When neither of these clients is enabled, gcc gives a warning (converted
+ // to error by -Werror) about the unused clientConfiguration parameter. We
+ // prevent that warning with AWS_UNREFERENCED_PARAM.
+ AWS_UNREFERENCED_PARAM(clientConfiguration);
+ AWS_LOGSTREAM_WARN(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, "SDK was built without an Http implementation, default http client factory can't create an Http client instance.");
+ return nullptr;
+#endif
+ }
+
+ std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String &uri, HttpMethod method,
+ const Aws::IOStreamFactory &streamFactory) const override
+ {
+ return CreateHttpRequest(URI(uri), method, streamFactory);
+ }
+
+ std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory) const override
+ {
+ auto request = Aws::MakeShared<Standard::StandardHttpRequest>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG, uri, method);
+ request->SetResponseStreamFactory(streamFactory);
+
+ return request;
+ }
+
+ void InitStaticState() override
+ {
+#if ENABLE_CURL_CLIENT
+ if(s_InitCleanupCurlFlag)
+ {
+ CurlHttpClient::InitGlobalState();
+ }
+#if !defined (_WIN32)
+ if(s_InstallSigPipeHandler)
+ {
+ ::signal(SIGPIPE, LogAndSwallowHandler);
+ }
+#endif
+#elif ENABLE_WINDOWS_IXML_HTTP_REQUEST_2_CLIENT
+ IXmlHttpRequest2HttpClient::InitCOM();
+#endif
+ }
+
+ virtual void CleanupStaticState() override
+ {
+#if ENABLE_CURL_CLIENT
+ if(s_InitCleanupCurlFlag)
+ {
+ CurlHttpClient::CleanupGlobalState();
+ }
+#endif
+ }
+ };
+
+ void SetInitCleanupCurlFlag(bool initCleanupFlag)
+ {
+ s_InitCleanupCurlFlag = initCleanupFlag;
+ }
+
+ void SetInstallSigPipeHandlerFlag(bool install)
+ {
+ s_InstallSigPipeHandler = install;
+ }
+
+ void InitHttp()
+ {
+ if(!GetHttpClientFactory())
+ {
+ GetHttpClientFactory() = Aws::MakeShared<DefaultHttpClientFactory>(HTTP_CLIENT_FACTORY_ALLOCATION_TAG);
+ }
+ GetHttpClientFactory()->InitStaticState();
+ }
+
+ void CleanupHttp()
+ {
+ if(GetHttpClientFactory())
+ {
+ GetHttpClientFactory()->CleanupStaticState();
+ GetHttpClientFactory() = nullptr;
+ }
+ }
+
+ void SetHttpClientFactory(const std::shared_ptr<HttpClientFactory>& factory)
+ {
+ CleanupHttp();
+ GetHttpClientFactory() = factory;
+ }
+
+ std::shared_ptr<HttpClient> CreateHttpClient(const Aws::Client::ClientConfiguration& clientConfiguration)
+ {
+ assert(GetHttpClientFactory());
+ return GetHttpClientFactory()->CreateHttpClient(clientConfiguration);
+ }
+
+ std::shared_ptr<HttpRequest> CreateHttpRequest(const Aws::String& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory)
+ {
+ assert(GetHttpClientFactory());
+ return GetHttpClientFactory()->CreateHttpRequest(uri, method, streamFactory);
+ }
+
+ std::shared_ptr<HttpRequest> CreateHttpRequest(const URI& uri, HttpMethod method, const Aws::IOStreamFactory& streamFactory)
+ {
+ assert(GetHttpClientFactory());
+ return GetHttpClientFactory()->CreateHttpRequest(uri, method, streamFactory);
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp
new file mode 100644
index 0000000000..95cb626c22
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpRequest.cpp
@@ -0,0 +1,40 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/HttpRequest.h>
+
+namespace Aws
+{
+namespace Http
+{
+
+const char DATE_HEADER[] = "date";
+const char AWS_DATE_HEADER[] = "X-Amz-Date";
+const char AWS_SECURITY_TOKEN[] = "X-Amz-Security-Token";
+const char ACCEPT_HEADER[] = "accept";
+const char ACCEPT_CHAR_SET_HEADER[] = "accept-charset";
+const char ACCEPT_ENCODING_HEADER[] = "accept-encoding";
+const char AUTHORIZATION_HEADER[] = "authorization";
+const char AWS_AUTHORIZATION_HEADER[] = "authorization";
+const char COOKIE_HEADER[] = "cookie";
+const char CONTENT_LENGTH_HEADER[] = "content-length";
+const char CONTENT_TYPE_HEADER[] = "content-type";
+const char TRANSFER_ENCODING_HEADER[] = "transfer-encoding";
+const char USER_AGENT_HEADER[] = "user-agent";
+const char VIA_HEADER[] = "via";
+const char HOST_HEADER[] = "host";
+const char AMZ_TARGET_HEADER[] = "x-amz-target";
+const char X_AMZ_EXPIRES_HEADER[] = "X-Amz-Expires";
+const char CONTENT_MD5_HEADER[] = "content-md5";
+const char API_VERSION_HEADER[] = "x-amz-api-version";
+const char SDK_INVOCATION_ID_HEADER[] = "amz-sdk-invocation-id";
+const char SDK_REQUEST_HEADER[] = "amz-sdk-request";
+const char CHUNKED_VALUE[] = "chunked";
+
+} // Http
+} // Aws
+
+
+
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp
new file mode 100644
index 0000000000..4d313e52f3
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/HttpTypes.cpp
@@ -0,0 +1,42 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/HttpTypes.h>
+#include <cassert>
+
+using namespace Aws::Http;
+
+namespace Aws
+{
+namespace Http
+{
+
+namespace HttpMethodMapper
+{
+const char* GetNameForHttpMethod(HttpMethod httpMethod)
+{
+ switch (httpMethod)
+ {
+ case HttpMethod::HTTP_GET:
+ return "GET";
+ case HttpMethod::HTTP_POST:
+ return "POST";
+ case HttpMethod::HTTP_DELETE:
+ return "DELETE";
+ case HttpMethod::HTTP_PUT:
+ return "PUT";
+ case HttpMethod::HTTP_HEAD:
+ return "HEAD";
+ case HttpMethod::HTTP_PATCH:
+ return "PATCH";
+ default:
+ assert(0);
+ return "GET";
+ }
+}
+
+} // namespace HttpMethodMapper
+} // namespace Http
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp
new file mode 100644
index 0000000000..5dcea06aab
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/Scheme.cpp
@@ -0,0 +1,54 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/Scheme.h>
+#include <aws/core/utils/memory/stl/AWSString.h>
+#include <aws/core/utils/StringUtils.h>
+
+using namespace Aws::Http;
+using namespace Aws::Utils;
+
+namespace Aws
+{
+namespace Http
+{
+namespace SchemeMapper
+{
+
+ const char* ToString(Scheme scheme)
+ {
+ switch (scheme)
+ {
+ case Scheme::HTTP:
+ return "http";
+ case Scheme::HTTPS:
+ return "https";
+ default:
+ return "http";
+ }
+ }
+
+ Scheme FromString(const char* name)
+ {
+ Aws::String trimmedString = StringUtils::Trim(name);
+ Aws::String loweredTrimmedString = StringUtils::ToLower(trimmedString.c_str());
+
+ if (loweredTrimmedString == "http")
+ {
+ return Scheme::HTTP;
+ }
+ //this branch is technically unneeded, but it is here so we don't have a subtle bug
+ //creep in as we extend this enum.
+ else if (loweredTrimmedString == "https")
+ {
+ return Scheme::HTTPS;
+ }
+
+ return Scheme::HTTPS;
+ }
+
+} // namespace SchemeMapper
+} // namespace Http
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp
new file mode 100644
index 0000000000..a2239df54b
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/URI.cpp
@@ -0,0 +1,510 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/URI.h>
+
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/memory/stl/AWSStringStream.h>
+#include <aws/core/utils/memory/stl/AWSSet.h>
+
+#include <cstdlib>
+#include <cctype>
+#include <cassert>
+#include <algorithm>
+#include <iomanip>
+
+using namespace Aws::Http;
+using namespace Aws::Utils;
+
+namespace Aws
+{
+namespace Http
+{
+
+const char* SEPARATOR = "://";
+
+} // namespace Http
+} // namespace Aws
+
+URI::URI() : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT)
+{
+}
+
+URI::URI(const Aws::String& uri) : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT)
+{
+ ParseURIParts(uri);
+}
+
+URI::URI(const char* uri) : m_scheme(Scheme::HTTP), m_port(HTTP_DEFAULT_PORT)
+{
+ ParseURIParts(uri);
+}
+
+URI& URI::operator =(const Aws::String& uri)
+{
+ this->ParseURIParts(uri);
+ return *this;
+}
+
+URI& URI::operator =(const char* uri)
+{
+ this->ParseURIParts(uri);
+ return *this;
+}
+
+bool URI::operator ==(const URI& other) const
+{
+ return CompareURIParts(other);
+}
+
+bool URI::operator ==(const Aws::String& other) const
+{
+ return CompareURIParts(other);
+}
+
+bool URI::operator ==(const char* other) const
+{
+ return CompareURIParts(other);
+}
+
+bool URI::operator !=(const URI& other) const
+{
+ return !(*this == other);
+}
+
+bool URI::operator !=(const Aws::String& other) const
+{
+ return !(*this == other);
+}
+
+bool URI::operator !=(const char* other) const
+{
+ return !(*this == other);
+}
+
+void URI::SetScheme(Scheme value)
+{
+ assert(value == Scheme::HTTP || value == Scheme::HTTPS);
+
+ if (value == Scheme::HTTP)
+ {
+ m_port = m_port == HTTPS_DEFAULT_PORT || m_port == 0 ? HTTP_DEFAULT_PORT : m_port;
+ m_scheme = value;
+ }
+ else if (value == Scheme::HTTPS)
+ {
+ m_port = m_port == HTTP_DEFAULT_PORT || m_port == 0 ? HTTPS_DEFAULT_PORT : m_port;
+ m_scheme = value;
+ }
+}
+
+Aws::String URI::URLEncodePathRFC3986(const Aws::String& path)
+{
+ if(path.empty())
+ {
+ return path;
+ }
+
+ const Aws::Vector<Aws::String> pathParts = StringUtils::Split(path, '/');
+ Aws::StringStream ss;
+ ss << std::hex << std::uppercase;
+
+ // escape characters appearing in a URL path according to RFC 3986
+ for (const auto& segment : pathParts)
+ {
+ ss << '/';
+ for(unsigned char c : segment) // alnum results in UB if the value of c is not unsigned char & is not EOF
+ {
+ // §2.3 unreserved characters
+ if (StringUtils::IsAlnum(c))
+ {
+ ss << c;
+ continue;
+ }
+ switch(c)
+ {
+ // §2.3 unreserved characters
+ case '-': case '_': case '.': case '~':
+ // The path section of the URL allow reserved characters to appear unescaped
+ // RFC 3986 §2.2 Reserved characters
+ // NOTE: this implementation does not accurately implement the RFC on purpose to accommodate for
+ // discrepancies in the implementations of URL encoding between AWS services for legacy reasons.
+ case '$': case '&': case ',':
+ case ':': case '=': case '@':
+ ss << c;
+ break;
+ default:
+ ss << '%' << std::setfill('0') << std::setw(2) << (int)((unsigned char)c) << std::setw(0);
+ }
+ }
+ }
+
+ //if the last character was also a slash, then add that back here.
+ if (path.back() == '/')
+ {
+ ss << '/';
+ }
+
+ return ss.str();
+}
+
+Aws::String URI::URLEncodePath(const Aws::String& path)
+{
+ Aws::Vector<Aws::String> pathParts = StringUtils::Split(path, '/');
+ Aws::StringStream ss;
+
+ for (Aws::Vector<Aws::String>::iterator iter = pathParts.begin(); iter != pathParts.end(); ++iter)
+ {
+ ss << '/' << StringUtils::URLEncode(iter->c_str());
+ }
+
+ //if the last character was also a slash, then add that back here.
+ if (path.length() > 0 && path[path.length() - 1] == '/')
+ {
+ ss << '/';
+ }
+
+ if (path.length() > 0 && path[0] != '/')
+ {
+ return ss.str().substr(1);
+ }
+ else
+ {
+ return ss.str();
+ }
+}
+
+void URI::SetPath(const Aws::String& value)
+{
+ const Aws::Vector<Aws::String> pathParts = StringUtils::Split(value, '/');
+ Aws::String path;
+ path.reserve(value.length() + 1/* in case we have to append slash before the path. */);
+
+ for (const auto& segment : pathParts)
+ {
+ path.push_back('/');
+ path.append(segment);
+ }
+
+ if (value.back() == '/')
+ {
+ path.push_back('/');
+ }
+ m_path = std::move(path);
+}
+
+//ugh, this isn't even part of the canonicalization spec. It is part of how our services have implemented their signers though....
+//it doesn't really hurt anything to reorder it though, so go ahead and sort the values for parameters with the same key
+void InsertValueOrderedParameter(QueryStringParameterCollection& queryParams, const Aws::String& key, const Aws::String& value)
+{
+ auto entriesAtKey = queryParams.equal_range(key);
+ for (auto& entry = entriesAtKey.first; entry != entriesAtKey.second; ++entry)
+ {
+ if (entry->second > value)
+ {
+ queryParams.emplace_hint(entry, key, value);
+ return;
+ }
+ }
+
+ queryParams.emplace(key, value);
+}
+
+QueryStringParameterCollection URI::GetQueryStringParameters(bool decode) const
+{
+ Aws::String queryString = GetQueryString();
+
+ QueryStringParameterCollection parameterCollection;
+
+ //if we actually have a query string
+ if (queryString.size() > 0)
+ {
+ size_t currentPos = 1, locationOfNextDelimiter = 1;
+
+ //while we have params left to parse
+ while (currentPos < queryString.size())
+ {
+ //find next key/value pair
+ locationOfNextDelimiter = queryString.find('&', currentPos);
+
+ Aws::String keyValuePair;
+
+ //if this isn't the last parameter
+ if (locationOfNextDelimiter != Aws::String::npos)
+ {
+ keyValuePair = queryString.substr(currentPos, locationOfNextDelimiter - currentPos);
+ }
+ //if it is the last parameter
+ else
+ {
+ keyValuePair = queryString.substr(currentPos);
+ }
+
+ //split on =
+ size_t locationOfEquals = keyValuePair.find('=');
+ Aws::String key = keyValuePair.substr(0, locationOfEquals);
+ Aws::String value = keyValuePair.substr(locationOfEquals + 1);
+
+ if(decode)
+ {
+ InsertValueOrderedParameter(parameterCollection, StringUtils::URLDecode(key.c_str()), StringUtils::URLDecode(value.c_str()));
+ }
+ else
+ {
+ InsertValueOrderedParameter(parameterCollection, key, value);
+ }
+
+ currentPos += keyValuePair.size() + 1;
+ }
+ }
+
+ return parameterCollection;
+}
+
+void URI::CanonicalizeQueryString()
+{
+ QueryStringParameterCollection sortedParameters = GetQueryStringParameters(false);
+ Aws::StringStream queryStringStream;
+
+ bool first = true;
+
+ if(sortedParameters.size() > 0)
+ {
+ queryStringStream << "?";
+ }
+
+ if(m_queryString.find('=') != std::string::npos)
+ {
+ for (QueryStringParameterCollection::iterator iter = sortedParameters.begin();
+ iter != sortedParameters.end(); ++iter)
+ {
+ if (!first)
+ {
+ queryStringStream << "&";
+ }
+
+ first = false;
+ queryStringStream << iter->first.c_str() << "=" << iter->second.c_str();
+ }
+
+ m_queryString = queryStringStream.str();
+ }
+}
+
+void URI::AddQueryStringParameter(const char* key, const Aws::String& value)
+{
+ if (m_queryString.size() <= 0)
+ {
+ m_queryString.append("?");
+ }
+ else
+ {
+ m_queryString.append("&");
+ }
+
+ m_queryString.append(StringUtils::URLEncode(key) + "=" + StringUtils::URLEncode(value.c_str()));
+}
+
+void URI::AddQueryStringParameter(const Aws::Map<Aws::String, Aws::String>& queryStringPairs)
+{
+ for(const auto& entry: queryStringPairs)
+ {
+ AddQueryStringParameter(entry.first.c_str(), entry.second);
+ }
+}
+
+void URI::SetQueryString(const Aws::String& str)
+{
+ m_queryString = "";
+
+ if (str.empty()) return;
+
+ if (str.front() != '?')
+ {
+ m_queryString.append("?").append(str);
+ }
+ else
+ {
+ m_queryString = str;
+ }
+}
+
+Aws::String URI::GetURIString(bool includeQueryString) const
+{
+ assert(m_authority.size() > 0);
+
+ Aws::StringStream ss;
+ ss << SchemeMapper::ToString(m_scheme) << SEPARATOR << m_authority;
+
+ if (m_scheme == Scheme::HTTP && m_port != HTTP_DEFAULT_PORT)
+ {
+ ss << ":" << m_port;
+ }
+ else if (m_scheme == Scheme::HTTPS && m_port != HTTPS_DEFAULT_PORT)
+ {
+ ss << ":" << m_port;
+ }
+
+ if(m_path != "/")
+ {
+ ss << URLEncodePathRFC3986(m_path);
+ }
+
+ if(includeQueryString)
+ {
+ ss << m_queryString;
+ }
+
+ return ss.str();
+}
+
+void URI::ParseURIParts(const Aws::String& uri)
+{
+ ExtractAndSetScheme(uri);
+ ExtractAndSetAuthority(uri);
+ ExtractAndSetPort(uri);
+ ExtractAndSetPath(uri);
+ ExtractAndSetQueryString(uri);
+}
+
+void URI::ExtractAndSetScheme(const Aws::String& uri)
+{
+ size_t posOfSeparator = uri.find(SEPARATOR);
+
+ if (posOfSeparator != Aws::String::npos)
+ {
+ Aws::String schemePortion = uri.substr(0, posOfSeparator);
+ SetScheme(SchemeMapper::FromString(schemePortion.c_str()));
+ }
+ else
+ {
+ SetScheme(Scheme::HTTP);
+ }
+}
+
+void URI::ExtractAndSetAuthority(const Aws::String& uri)
+{
+ size_t authorityStart = uri.find(SEPARATOR);
+
+ if (authorityStart == Aws::String::npos)
+ {
+ authorityStart = 0;
+ }
+ else
+ {
+ authorityStart += 3;
+ }
+
+ size_t posOfEndOfAuthorityPort = uri.find(':', authorityStart);
+ size_t posOfEndOfAuthoritySlash = uri.find('/', authorityStart);
+ size_t posOfEndOfAuthorityQuery = uri.find('?', authorityStart);
+ size_t posEndOfAuthority = (std::min)({posOfEndOfAuthorityPort, posOfEndOfAuthoritySlash, posOfEndOfAuthorityQuery});
+ if (posEndOfAuthority == Aws::String::npos)
+ {
+ posEndOfAuthority = uri.length();
+ }
+
+ SetAuthority(uri.substr(authorityStart, posEndOfAuthority - authorityStart));
+}
+
+void URI::ExtractAndSetPort(const Aws::String& uri)
+{
+ size_t authorityStart = uri.find(SEPARATOR);
+
+ if(authorityStart == Aws::String::npos)
+ {
+ authorityStart = 0;
+ }
+ else
+ {
+ authorityStart += 3;
+ }
+
+ size_t positionOfPortDelimiter = uri.find(':', authorityStart);
+
+ bool hasPort = positionOfPortDelimiter != Aws::String::npos;
+
+ if ((uri.find('/', authorityStart) < positionOfPortDelimiter) || (uri.find('?', authorityStart) < positionOfPortDelimiter))
+ {
+ hasPort = false;
+ }
+
+ if (hasPort)
+ {
+ Aws::String strPort;
+
+ size_t i = positionOfPortDelimiter + 1;
+ char currentDigit = uri[i];
+
+ while (std::isdigit(currentDigit))
+ {
+ strPort += currentDigit;
+ currentDigit = uri[++i];
+ }
+
+ SetPort(static_cast<uint16_t>(atoi(strPort.c_str())));
+ }
+}
+
+void URI::ExtractAndSetPath(const Aws::String& uri)
+{
+ size_t authorityStart = uri.find(SEPARATOR);
+
+ if (authorityStart == Aws::String::npos)
+ {
+ authorityStart = 0;
+ }
+ else
+ {
+ authorityStart += 3;
+ }
+
+ size_t pathEnd = uri.find('?');
+
+ if (pathEnd == Aws::String::npos)
+ {
+ pathEnd = uri.length();
+ }
+
+ Aws::String authorityAndPath = uri.substr(authorityStart, pathEnd - authorityStart);
+
+ size_t pathStart = authorityAndPath.find('/');
+
+ if (pathStart != Aws::String::npos)
+ {
+ SetPath(authorityAndPath.substr(pathStart, pathEnd - pathStart));
+ }
+ else
+ {
+ SetPath("/");
+ }
+}
+
+void URI::ExtractAndSetQueryString(const Aws::String& uri)
+{
+ size_t queryStart = uri.find('?');
+
+ if (queryStart != Aws::String::npos)
+ {
+ m_queryString = uri.substr(queryStart);
+ }
+}
+
+Aws::String URI::GetFormParameters() const
+{
+ if(m_queryString.length() == 0)
+ {
+ return "";
+ }
+ else
+ {
+ return m_queryString.substr(1);
+ }
+}
+
+bool URI::CompareURIParts(const URI& other) const
+{
+ return m_scheme == other.m_scheme && m_authority == other.m_authority && m_path == other.m_path && m_queryString == other.m_queryString;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp
new file mode 100644
index 0000000000..1a965cd795
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp
@@ -0,0 +1,153 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/curl/CurlHandleContainer.h>
+#include <aws/core/utils/logging/LogMacros.h>
+
+#include <algorithm>
+
+using namespace Aws::Utils::Logging;
+using namespace Aws::Http;
+
+static const char* CURL_HANDLE_CONTAINER_TAG = "CurlHandleContainer";
+
+
+CurlHandleContainer::CurlHandleContainer(unsigned maxSize, long httpRequestTimeout, long connectTimeout, bool enableTcpKeepAlive,
+ unsigned long tcpKeepAliveIntervalMs, long lowSpeedTime, unsigned long lowSpeedLimit) :
+ m_maxPoolSize(maxSize), m_httpRequestTimeout(httpRequestTimeout), m_connectTimeout(connectTimeout), m_enableTcpKeepAlive(enableTcpKeepAlive),
+ m_tcpKeepAliveIntervalMs(tcpKeepAliveIntervalMs), m_lowSpeedTime(lowSpeedTime), m_lowSpeedLimit(lowSpeedLimit), m_poolSize(0)
+{
+ AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Initializing CurlHandleContainer with size " << maxSize);
+}
+
+CurlHandleContainer::~CurlHandleContainer()
+{
+ AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Cleaning up CurlHandleContainer.");
+ for (CURL* handle : m_handleContainer.ShutdownAndWait(m_poolSize))
+ {
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Cleaning up " << handle);
+ curl_easy_cleanup(handle);
+ }
+}
+
+CURL* CurlHandleContainer::AcquireCurlHandle()
+{
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Attempting to acquire curl connection.");
+
+ if(!m_handleContainer.HasResourcesAvailable())
+ {
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "No current connections available in pool. Attempting to create new connections.");
+ CheckAndGrowPool();
+ }
+
+ CURL* handle = m_handleContainer.Acquire();
+ AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Connection has been released. Continuing.");
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Returning connection handle " << handle);
+ return handle;
+}
+
+void CurlHandleContainer::ReleaseCurlHandle(CURL* handle)
+{
+ if (handle)
+ {
+ curl_easy_reset(handle);
+ SetDefaultOptionsOnHandle(handle);
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Releasing curl handle " << handle);
+ m_handleContainer.Release(handle);
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Notified waiting threads.");
+ }
+}
+
+void CurlHandleContainer::DestroyCurlHandle(CURL* handle)
+{
+ if (!handle)
+ {
+ return;
+ }
+
+ curl_easy_cleanup(handle);
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Destroy curl handle: " << handle);
+ {
+ std::lock_guard<std::mutex> locker(m_containerLock);
+ // Other threads could be blocked and waiting on m_handleContainer.Acquire()
+ // If the handle is not released back to the pool, it could create a deadlock
+ // Create a new handle and release that into the pool
+ handle = CreateCurlHandleInPool();
+ }
+ if (handle)
+ {
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Created replacement handle and released to pool: " << handle);
+ }
+}
+
+
+CURL* CurlHandleContainer::CreateCurlHandleInPool()
+{
+ CURL* curlHandle = curl_easy_init();
+
+ if (curlHandle)
+ {
+ SetDefaultOptionsOnHandle(curlHandle);
+ m_handleContainer.Release(curlHandle);
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(CURL_HANDLE_CONTAINER_TAG, "curl_easy_init failed to allocate.");
+ }
+ return curlHandle;
+}
+
+bool CurlHandleContainer::CheckAndGrowPool()
+{
+ std::lock_guard<std::mutex> locker(m_containerLock);
+ if (m_poolSize < m_maxPoolSize)
+ {
+ unsigned multiplier = m_poolSize > 0 ? m_poolSize : 1;
+ unsigned amountToAdd = (std::min)(multiplier * 2, m_maxPoolSize - m_poolSize);
+ AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "attempting to grow pool size by " << amountToAdd);
+
+ unsigned actuallyAdded = 0;
+ for (unsigned i = 0; i < amountToAdd; ++i)
+ {
+ CURL* curlHandle = CreateCurlHandleInPool();
+
+ if (curlHandle)
+ {
+ ++actuallyAdded;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Pool grown by " << actuallyAdded);
+ m_poolSize += actuallyAdded;
+
+ return actuallyAdded > 0;
+ }
+
+ AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Pool cannot be grown any further, already at max size.");
+
+ return false;
+}
+
+void CurlHandleContainer::SetDefaultOptionsOnHandle(CURL* handle)
+{
+ //for timeouts to work in a multi-threaded context,
+ //always turn signals off. This also forces dns queries to
+ //not be included in the timeout calculations.
+ curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L);
+ curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, m_httpRequestTimeout);
+ curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT_MS, m_connectTimeout);
+ curl_easy_setopt(handle, CURLOPT_LOW_SPEED_LIMIT, m_lowSpeedLimit);
+ curl_easy_setopt(handle, CURLOPT_LOW_SPEED_TIME, m_lowSpeedTime < 1000 ? (m_lowSpeedTime == 0 ? 0 : 1) : m_lowSpeedTime / 1000);
+ curl_easy_setopt(handle, CURLOPT_TCP_KEEPALIVE, m_enableTcpKeepAlive ? 1L : 0L);
+ curl_easy_setopt(handle, CURLOPT_TCP_KEEPINTVL, m_tcpKeepAliveIntervalMs / 1000);
+ curl_easy_setopt(handle, CURLOPT_TCP_KEEPIDLE, m_tcpKeepAliveIntervalMs / 1000);
+#ifdef CURL_HAS_H2
+ curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
+#endif
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp
new file mode 100644
index 0000000000..2fb9cc9643
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp
@@ -0,0 +1,730 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/curl/CurlHttpClient.h>
+#include <aws/core/http/HttpRequest.h>
+#include <aws/core/http/standard/StandardHttpResponse.h>
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/ratelimiter/RateLimiterInterface.h>
+#include <aws/core/utils/DateTime.h>
+#include <aws/core/monitoring/HttpClientMetrics.h>
+#include <cassert>
+#include <algorithm>
+
+
+using namespace Aws::Client;
+using namespace Aws::Http;
+using namespace Aws::Http::Standard;
+using namespace Aws::Utils;
+using namespace Aws::Utils::Logging;
+using namespace Aws::Monitoring;
+
+#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT
+
+static const char* MemTag = "libcurl";
+static size_t offset = sizeof(size_t);
+
+static void* malloc_callback(size_t size)
+{
+ char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, size + offset));
+ std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem);
+ *pointerToSize = size;
+ return reinterpret_cast<void*>(newMem + offset);
+}
+
+static void free_callback(void* ptr)
+{
+ if(ptr)
+ {
+ char* shiftedMemory = reinterpret_cast<char*>(ptr);
+ Aws::Free(shiftedMemory - offset);
+ }
+}
+
+static void* realloc_callback(void* ptr, size_t size)
+{
+ if(!ptr)
+ {
+ return malloc_callback(size);
+ }
+
+
+ if(!size && ptr)
+ {
+ free_callback(ptr);
+ return nullptr;
+ }
+
+ char* originalLenCharPtr = reinterpret_cast<char*>(ptr) - offset;
+ size_t originalLen = *reinterpret_cast<size_t*>(originalLenCharPtr);
+
+ char* rawMemory = reinterpret_cast<char*>(Aws::Malloc(MemTag, size + offset));
+ if(rawMemory)
+ {
+ std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(rawMemory);
+ *pointerToSize = size;
+
+ size_t copyLength = (std::min)(originalLen, size);
+#ifdef _MSC_VER
+ memcpy_s(rawMemory + offset, size, ptr, copyLength);
+#else
+ memcpy(rawMemory + offset, ptr, copyLength);
+#endif
+ free_callback(ptr);
+ return reinterpret_cast<void*>(rawMemory + offset);
+ }
+ else
+ {
+ return ptr;
+ }
+
+}
+
+static void* calloc_callback(size_t nmemb, size_t size)
+{
+ size_t dataSize = nmemb * size;
+ char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, dataSize + offset));
+ std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem);
+ *pointerToSize = dataSize;
+#ifdef _MSC_VER
+ memset_s(newMem + offset, dataSize, 0, dataSize);
+#else
+ memset(newMem + offset, 0, dataSize);
+#endif
+
+ return reinterpret_cast<void*>(newMem + offset);
+}
+
+static char* strdup_callback(const char* str)
+{
+ size_t len = strlen(str) + 1;
+ size_t newLen = len + offset;
+ char* newMem = reinterpret_cast<char*>(Aws::Malloc(MemTag, newLen));
+
+ if(newMem)
+ {
+ std::size_t* pointerToSize = reinterpret_cast<std::size_t*>(newMem);
+ *pointerToSize = len;
+#ifdef _MSC_VER
+ memcpy_s(newMem + offset, len, str, len);
+#else
+ memcpy(newMem + offset, str, len);
+#endif
+ return newMem + offset;
+ }
+ return nullptr;
+}
+
+#endif
+
+struct CurlWriteCallbackContext
+{
+ CurlWriteCallbackContext(const CurlHttpClient* client,
+ HttpRequest* request,
+ HttpResponse* response,
+ Aws::Utils::RateLimits::RateLimiterInterface* rateLimiter) :
+ m_client(client),
+ m_request(request),
+ m_response(response),
+ m_rateLimiter(rateLimiter),
+ m_numBytesResponseReceived(0)
+ {}
+
+ const CurlHttpClient* m_client;
+ HttpRequest* m_request;
+ HttpResponse* m_response;
+ Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter;
+ int64_t m_numBytesResponseReceived;
+};
+
+struct CurlReadCallbackContext
+{
+ CurlReadCallbackContext(const CurlHttpClient* client, HttpRequest* request, Aws::Utils::RateLimits::RateLimiterInterface* limiter) :
+ m_client(client),
+ m_rateLimiter(limiter),
+ m_request(request)
+ {}
+
+ const CurlHttpClient* m_client;
+ CURL* m_curlHandle;
+ Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter;
+ HttpRequest* m_request;
+};
+
+static const char* CURL_HTTP_CLIENT_TAG = "CurlHttpClient";
+
+static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata)
+{
+ if (ptr)
+ {
+ CurlWriteCallbackContext* context = reinterpret_cast<CurlWriteCallbackContext*>(userdata);
+
+ const CurlHttpClient* client = context->m_client;
+ if(!client->ContinueRequest(*context->m_request) || !client->IsRequestProcessingEnabled())
+ {
+ return 0;
+ }
+
+ HttpResponse* response = context->m_response;
+ size_t sizeToWrite = size * nmemb;
+ if (context->m_rateLimiter)
+ {
+ context->m_rateLimiter->ApplyAndPayForCost(static_cast<int64_t>(sizeToWrite));
+ }
+
+ response->GetResponseBody().write(ptr, static_cast<std::streamsize>(sizeToWrite));
+ if (context->m_request->IsEventStreamRequest())
+ {
+ response->GetResponseBody().flush();
+ }
+ auto& receivedHandler = context->m_request->GetDataReceivedEventHandler();
+ if (receivedHandler)
+ {
+ receivedHandler(context->m_request, context->m_response, static_cast<long long>(sizeToWrite));
+ }
+
+ AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, sizeToWrite << " bytes written to response.");
+ context->m_numBytesResponseReceived += sizeToWrite;
+ return sizeToWrite;
+ }
+ return 0;
+}
+
+static size_t WriteHeader(char* ptr, size_t size, size_t nmemb, void* userdata)
+{
+ if (ptr)
+ {
+ CurlWriteCallbackContext* context = reinterpret_cast<CurlWriteCallbackContext*>(userdata);
+ AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, ptr);
+ HttpResponse* response = context->m_response;
+ Aws::String headerLine(ptr);
+ Aws::Vector<Aws::String> keyValuePair = StringUtils::Split(headerLine, ':', 2);
+
+ if (keyValuePair.size() == 2)
+ {
+ response->AddHeader(StringUtils::Trim(keyValuePair[0].c_str()), StringUtils::Trim(keyValuePair[1].c_str()));
+ }
+
+ return size * nmemb;
+ }
+ return 0;
+}
+
+
+static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata)
+{
+ CurlReadCallbackContext* context = reinterpret_cast<CurlReadCallbackContext*>(userdata);
+ if(context == nullptr)
+ {
+ return 0;
+ }
+
+ const CurlHttpClient* client = context->m_client;
+ if(!client->ContinueRequest(*context->m_request) || !client->IsRequestProcessingEnabled())
+ {
+ return CURL_READFUNC_ABORT;
+ }
+
+ HttpRequest* request = context->m_request;
+ const std::shared_ptr<Aws::IOStream>& ioStream = request->GetContentBody();
+
+ const size_t amountToRead = size * nmemb;
+ if (ioStream != nullptr && amountToRead > 0)
+ {
+ if (request->IsEventStreamRequest())
+ {
+ // Waiting for next available character to read.
+ // Without peek(), readsome() will keep reading 0 byte from the stream.
+ ioStream->peek();
+ ioStream->readsome(ptr, amountToRead);
+ }
+ else
+ {
+ ioStream->read(ptr, amountToRead);
+ }
+ size_t amountRead = static_cast<size_t>(ioStream->gcount());
+ auto& sentHandler = request->GetDataSentEventHandler();
+ if (sentHandler)
+ {
+ sentHandler(request, static_cast<long long>(amountRead));
+ }
+
+ if (context->m_rateLimiter)
+ {
+ context->m_rateLimiter->ApplyAndPayForCost(static_cast<int64_t>(amountRead));
+ }
+
+ return amountRead;
+ }
+
+ return 0;
+}
+
+static size_t SeekBody(void* userdata, curl_off_t offset, int origin)
+{
+ CurlReadCallbackContext* context = reinterpret_cast<CurlReadCallbackContext*>(userdata);
+ if(context == nullptr)
+ {
+ return CURL_SEEKFUNC_FAIL;
+ }
+
+ const CurlHttpClient* client = context->m_client;
+ if(!client->ContinueRequest(*context->m_request) || !client->IsRequestProcessingEnabled())
+ {
+ return CURL_SEEKFUNC_FAIL;
+ }
+
+ HttpRequest* request = context->m_request;
+ const std::shared_ptr<Aws::IOStream>& ioStream = request->GetContentBody();
+
+ std::ios_base::seekdir dir;
+ switch(origin)
+ {
+ case SEEK_SET:
+ dir = std::ios_base::beg;
+ break;
+ case SEEK_CUR:
+ dir = std::ios_base::cur;
+ break;
+ case SEEK_END:
+ dir = std::ios_base::end;
+ break;
+ default:
+ return CURL_SEEKFUNC_FAIL;
+ }
+
+ ioStream->clear();
+ ioStream->seekg(offset, dir);
+ if (ioStream->fail()) {
+ return CURL_SEEKFUNC_CANTSEEK;
+ }
+
+ return CURL_SEEKFUNC_OK;
+}
+
+void SetOptCodeForHttpMethod(CURL* requestHandle, const std::shared_ptr<HttpRequest>& request)
+{
+ switch (request->GetMethod())
+ {
+ case HttpMethod::HTTP_GET:
+ curl_easy_setopt(requestHandle, CURLOPT_HTTPGET, 1L);
+ break;
+ case HttpMethod::HTTP_POST:
+ if (request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER) && request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER) == "0")
+ {
+ curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "POST");
+ }
+ else
+ {
+ curl_easy_setopt(requestHandle, CURLOPT_POST, 1L);
+ }
+ break;
+ case HttpMethod::HTTP_PUT:
+ if ((!request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER) || request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER) == "0") &&
+ !request->HasHeader(Aws::Http::TRANSFER_ENCODING_HEADER))
+ {
+ curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PUT");
+ }
+ else
+ {
+ curl_easy_setopt(requestHandle, CURLOPT_PUT, 1L);
+ }
+ break;
+ case HttpMethod::HTTP_HEAD:
+ curl_easy_setopt(requestHandle, CURLOPT_HTTPGET, 1L);
+ curl_easy_setopt(requestHandle, CURLOPT_NOBODY, 1L);
+ break;
+ case HttpMethod::HTTP_PATCH:
+ if ((!request->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER)|| request->GetHeaderValue(Aws::Http::CONTENT_LENGTH_HEADER) == "0") &&
+ !request->HasHeader(Aws::Http::TRANSFER_ENCODING_HEADER))
+ {
+ curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PATCH");
+ }
+ else
+ {
+ curl_easy_setopt(requestHandle, CURLOPT_POST, 1L);
+ curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "PATCH");
+ }
+
+ break;
+ case HttpMethod::HTTP_DELETE:
+ curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
+ break;
+ default:
+ assert(0);
+ curl_easy_setopt(requestHandle, CURLOPT_CUSTOMREQUEST, "GET");
+ break;
+ }
+}
+
+
+std::atomic<bool> CurlHttpClient::isInit(false);
+
+void CurlHttpClient::InitGlobalState()
+{
+ if (!isInit)
+ {
+ auto curlVersionData = curl_version_info(CURLVERSION_NOW);
+ AWS_LOGSTREAM_INFO(CURL_HTTP_CLIENT_TAG, "Initializing Curl library with version: " << curlVersionData->version
+ << ", ssl version: " << curlVersionData->ssl_version);
+ isInit = true;
+#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT
+ curl_global_init_mem(CURL_GLOBAL_ALL, &malloc_callback, &free_callback, &realloc_callback, &strdup_callback, &calloc_callback);
+#else
+ curl_global_init(CURL_GLOBAL_ALL);
+#endif
+ }
+}
+
+
+void CurlHttpClient::CleanupGlobalState()
+{
+ curl_global_cleanup();
+}
+
+Aws::String CurlInfoTypeToString(curl_infotype type)
+{
+ switch(type)
+ {
+ case CURLINFO_TEXT:
+ return "Text";
+
+ case CURLINFO_HEADER_IN:
+ return "HeaderIn";
+
+ case CURLINFO_HEADER_OUT:
+ return "HeaderOut";
+
+ case CURLINFO_DATA_IN:
+ return "DataIn";
+
+ case CURLINFO_DATA_OUT:
+ return "DataOut";
+
+ case CURLINFO_SSL_DATA_IN:
+ return "SSLDataIn";
+
+ case CURLINFO_SSL_DATA_OUT:
+ return "SSLDataOut";
+
+ default:
+ return "Unknown";
+ }
+}
+
+int CurlDebugCallback(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr)
+{
+ AWS_UNREFERENCED_PARAM(handle);
+ AWS_UNREFERENCED_PARAM(userptr);
+
+ if(type == CURLINFO_SSL_DATA_IN || type == CURLINFO_SSL_DATA_OUT)
+ {
+ AWS_LOGSTREAM_DEBUG("CURL", "(" << CurlInfoTypeToString(type) << ") " << size << "bytes");
+ }
+ else
+ {
+ Aws::String debugString(data, size);
+ AWS_LOGSTREAM_DEBUG("CURL", "(" << CurlInfoTypeToString(type) << ") " << debugString);
+ }
+
+ return 0;
+}
+
+
+CurlHttpClient::CurlHttpClient(const ClientConfiguration& clientConfig) :
+ Base(),
+ m_curlHandleContainer(clientConfig.maxConnections, clientConfig.httpRequestTimeoutMs, clientConfig.connectTimeoutMs, clientConfig.enableTcpKeepAlive,
+ clientConfig.tcpKeepAliveIntervalMs, clientConfig.requestTimeoutMs, clientConfig.lowSpeedLimit),
+ m_isUsingProxy(!clientConfig.proxyHost.empty()), m_proxyUserName(clientConfig.proxyUserName),
+ m_proxyPassword(clientConfig.proxyPassword), m_proxyScheme(SchemeMapper::ToString(clientConfig.proxyScheme)), m_proxyHost(clientConfig.proxyHost),
+ m_proxySSLCertPath(clientConfig.proxySSLCertPath), m_proxySSLCertType(clientConfig.proxySSLCertType),
+ m_proxySSLKeyPath(clientConfig.proxySSLKeyPath), m_proxySSLKeyType(clientConfig.proxySSLKeyType),
+ m_proxyKeyPasswd(clientConfig.proxySSLKeyPassword),
+ m_proxyPort(clientConfig.proxyPort), m_verifySSL(clientConfig.verifySSL), m_caPath(clientConfig.caPath),
+ m_caFile(clientConfig.caFile), m_proxyCaPath(clientConfig.proxyCaPath), m_proxyCaFile(clientConfig.proxyCaFile),
+ m_disableExpectHeader(clientConfig.disableExpectHeader)
+{
+ if (clientConfig.followRedirects == FollowRedirectsPolicy::NEVER ||
+ (clientConfig.followRedirects == FollowRedirectsPolicy::DEFAULT && clientConfig.region == Aws::Region::AWS_GLOBAL))
+ {
+ m_allowRedirects = false;
+ }
+ else
+ {
+ m_allowRedirects = true;
+ }
+}
+
+
+std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr<HttpRequest>& request,
+ Aws::Utils::RateLimits::RateLimiterInterface* readLimiter,
+ Aws::Utils::RateLimits::RateLimiterInterface* writeLimiter) const
+{
+ URI uri = request->GetUri();
+ Aws::String url = uri.GetURIString();
+ std::shared_ptr<HttpResponse> response = Aws::MakeShared<StandardHttpResponse>(CURL_HTTP_CLIENT_TAG, request);
+
+ AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Making request to " << url);
+ struct curl_slist* headers = NULL;
+
+ if (writeLimiter != nullptr)
+ {
+ writeLimiter->ApplyAndPayForCost(request->GetSize());
+ }
+
+ Aws::StringStream headerStream;
+ HeaderValueCollection requestHeaders = request->GetHeaders();
+
+ AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Including headers:");
+ for (auto& requestHeader : requestHeaders)
+ {
+ headerStream.str("");
+ headerStream << requestHeader.first << ": " << requestHeader.second;
+ Aws::String headerString = headerStream.str();
+ AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, headerString);
+ headers = curl_slist_append(headers, headerString.c_str());
+ }
+
+ if (!request->HasHeader(Http::TRANSFER_ENCODING_HEADER))
+ {
+ headers = curl_slist_append(headers, "transfer-encoding:");
+ }
+
+ if (!request->HasHeader(Http::CONTENT_LENGTH_HEADER))
+ {
+ headers = curl_slist_append(headers, "content-length:");
+ }
+
+ if (!request->HasHeader(Http::CONTENT_TYPE_HEADER))
+ {
+ headers = curl_slist_append(headers, "content-type:");
+ }
+
+ // Discard Expect header so as to avoid using multiple payloads to send a http request (header + body)
+ if (m_disableExpectHeader)
+ {
+ headers = curl_slist_append(headers, "Expect:");
+ }
+
+ CURL* connectionHandle = m_curlHandleContainer.AcquireCurlHandle();
+
+ if (connectionHandle)
+ {
+ AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Obtained connection handle " << connectionHandle);
+
+ if (headers)
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, headers);
+ }
+
+ CurlWriteCallbackContext writeContext(this, request.get(), response.get(), readLimiter);
+ CurlReadCallbackContext readContext(this, request.get(), writeLimiter);
+
+ SetOptCodeForHttpMethod(connectionHandle, request);
+
+ curl_easy_setopt(connectionHandle, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(connectionHandle, CURLOPT_WRITEFUNCTION, WriteData);
+ curl_easy_setopt(connectionHandle, CURLOPT_WRITEDATA, &writeContext);
+ curl_easy_setopt(connectionHandle, CURLOPT_HEADERFUNCTION, WriteHeader);
+ curl_easy_setopt(connectionHandle, CURLOPT_HEADERDATA, &writeContext);
+
+ //we only want to override the default path if someone has explicitly told us to.
+ if(!m_caPath.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_CAPATH, m_caPath.c_str());
+ }
+ if(!m_caFile.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_CAINFO, m_caFile.c_str());
+ }
+
+ // only set by android test builds because the emulator is missing a cert needed for aws services
+#ifdef TEST_CERT_PATH
+ curl_easy_setopt(connectionHandle, CURLOPT_CAPATH, TEST_CERT_PATH);
+#endif // TEST_CERT_PATH
+
+ if (m_verifySSL)
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYPEER, 1L);
+ curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYHOST, 2L);
+
+#if LIBCURL_VERSION_MAJOR >= 7
+#if LIBCURL_VERSION_MINOR >= 34
+ curl_easy_setopt(connectionHandle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
+#endif //LIBCURL_VERSION_MINOR
+#endif //LIBCURL_VERSION_MAJOR
+ }
+ else
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(connectionHandle, CURLOPT_SSL_VERIFYHOST, 0L);
+ }
+
+ if (m_allowRedirects)
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_FOLLOWLOCATION, 1L);
+ }
+ else
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_FOLLOWLOCATION, 0L);
+ }
+
+#ifdef ENABLE_CURL_LOGGING
+ curl_easy_setopt(connectionHandle, CURLOPT_VERBOSE, 1);
+ curl_easy_setopt(connectionHandle, CURLOPT_DEBUGFUNCTION, CurlDebugCallback);
+#endif
+ if (m_isUsingProxy)
+ {
+ Aws::StringStream ss;
+ ss << m_proxyScheme << "://" << m_proxyHost;
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY, ss.str().c_str());
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXYPORT, (long) m_proxyPort);
+ if(!m_proxyCaPath.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY_CAPATH, m_proxyCaPath.c_str());
+ }
+ if(!m_proxyCaFile.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY_CAINFO, m_proxyCaFile.c_str());
+ }
+ if (!m_proxyUserName.empty() || !m_proxyPassword.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXYUSERNAME, m_proxyUserName.c_str());
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXYPASSWORD, m_proxyPassword.c_str());
+ }
+#ifdef CURL_HAS_TLS_PROXY
+ if (!m_proxySSLCertPath.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY_SSLCERT, m_proxySSLCertPath.c_str());
+ if (!m_proxySSLCertType.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY_SSLCERTTYPE, m_proxySSLCertType.c_str());
+ }
+ }
+ if (!m_proxySSLKeyPath.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY_SSLKEY, m_proxySSLKeyPath.c_str());
+ if (!m_proxySSLKeyType.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY_SSLKEYTYPE, m_proxySSLKeyType.c_str());
+ }
+ if (!m_proxyKeyPasswd.empty())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY_KEYPASSWD, m_proxyKeyPasswd.c_str());
+ }
+ }
+#endif //CURL_HAS_TLS_PROXY
+ }
+ else
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_PROXY, "");
+ }
+
+ if (request->GetContentBody())
+ {
+ curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBody);
+ curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &readContext);
+ curl_easy_setopt(connectionHandle, CURLOPT_SEEKFUNCTION, SeekBody);
+ curl_easy_setopt(connectionHandle, CURLOPT_SEEKDATA, &readContext);
+ }
+
+ OverrideOptionsOnConnectionHandle(connectionHandle);
+ Aws::Utils::DateTime startTransmissionTime = Aws::Utils::DateTime::Now();
+ CURLcode curlResponseCode = curl_easy_perform(connectionHandle);
+ bool shouldContinueRequest = ContinueRequest(*request);
+ if (curlResponseCode != CURLE_OK && shouldContinueRequest)
+ {
+ response->SetClientErrorType(CoreErrors::NETWORK_CONNECTION);
+ Aws::StringStream ss;
+ ss << "curlCode: " << curlResponseCode << ", " << curl_easy_strerror(curlResponseCode);
+ response->SetClientErrorMessage(ss.str());
+ AWS_LOGSTREAM_ERROR(CURL_HTTP_CLIENT_TAG, "Curl returned error code " << curlResponseCode
+ << " - " << curl_easy_strerror(curlResponseCode));
+ }
+ else if(!shouldContinueRequest)
+ {
+ response->SetClientErrorType(CoreErrors::USER_CANCELLED);
+ response->SetClientErrorMessage("Request cancelled by user's continuation handler");
+ }
+ else
+ {
+ long responseCode;
+ curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &responseCode);
+ response->SetResponseCode(static_cast<HttpResponseCode>(responseCode));
+ AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned http response code " << responseCode);
+
+ char* contentType = nullptr;
+ curl_easy_getinfo(connectionHandle, CURLINFO_CONTENT_TYPE, &contentType);
+ if (contentType)
+ {
+ response->SetContentType(contentType);
+ AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned content type " << contentType);
+ }
+
+ if (request->GetMethod() != HttpMethod::HTTP_HEAD &&
+ writeContext.m_client->IsRequestProcessingEnabled() &&
+ response->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER))
+ {
+ const Aws::String& contentLength = response->GetHeader(Aws::Http::CONTENT_LENGTH_HEADER);
+ int64_t numBytesResponseReceived = writeContext.m_numBytesResponseReceived;
+ AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response content-length header: " << contentLength);
+ AWS_LOGSTREAM_TRACE(CURL_HTTP_CLIENT_TAG, "Response body length: " << numBytesResponseReceived);
+ if (StringUtils::ConvertToInt64(contentLength.c_str()) != numBytesResponseReceived)
+ {
+ response->SetClientErrorType(CoreErrors::NETWORK_CONNECTION);
+ response->SetClientErrorMessage("Response body length doesn't match the content-length header.");
+ AWS_LOGSTREAM_ERROR(CURL_HTTP_CLIENT_TAG, "Response body length doesn't match the content-length header.");
+ }
+ }
+
+ AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Releasing curl handle " << connectionHandle);
+ }
+
+ double timep;
+ CURLcode ret = curl_easy_getinfo(connectionHandle, CURLINFO_NAMELOOKUP_TIME, &timep); // DNS Resolve Latency, seconds.
+ if (ret == CURLE_OK)
+ {
+ request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::DnsLatency), static_cast<int64_t>(timep * 1000));// to milliseconds
+ }
+
+ ret = curl_easy_getinfo(connectionHandle, CURLINFO_STARTTRANSFER_TIME, &timep); // Connect Latency
+ if (ret == CURLE_OK)
+ {
+ request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::ConnectLatency), static_cast<int64_t>(timep * 1000));
+ }
+
+ ret = curl_easy_getinfo(connectionHandle, CURLINFO_APPCONNECT_TIME, &timep); // Ssl Latency
+ if (ret == CURLE_OK)
+ {
+ request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::SslLatency), static_cast<int64_t>(timep * 1000));
+ }
+
+ const char* ip = nullptr;
+ auto curlGetInfoResult = curl_easy_getinfo(connectionHandle, CURLINFO_PRIMARY_IP, &ip); // Get the IP address of the remote endpoint
+ if (curlGetInfoResult == CURLE_OK && ip)
+ {
+ request->SetResolvedRemoteHost(ip);
+ }
+ if (curlResponseCode != CURLE_OK)
+ {
+ m_curlHandleContainer.DestroyCurlHandle(connectionHandle);
+ }
+ else
+ {
+ m_curlHandleContainer.ReleaseCurlHandle(connectionHandle);
+ }
+ //go ahead and flush the response body stream
+ response->GetResponseBody().flush();
+ request->AddRequestMetric(GetHttpClientMetricNameByType(HttpClientMetricsType::RequestLatency), (DateTime::Now() - startTransmissionTime).count());
+ }
+
+ if (headers)
+ {
+ curl_slist_free_all(headers);
+ }
+
+ return response;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp
new file mode 100644
index 0000000000..47a0ee4fac
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpRequest.cpp
@@ -0,0 +1,104 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/standard/StandardHttpRequest.h>
+
+#include <aws/core/utils/StringUtils.h>
+
+#include <iostream>
+#include <algorithm>
+#include <cassert>
+
+using namespace Aws::Http;
+using namespace Aws::Http::Standard;
+using namespace Aws::Utils;
+
+static bool IsDefaultPort(const URI& uri)
+{
+ switch(uri.GetPort())
+ {
+ case 80:
+ return uri.GetScheme() == Scheme::HTTP;
+ case 443:
+ return uri.GetScheme() == Scheme::HTTPS;
+ default:
+ return false;
+ }
+}
+
+StandardHttpRequest::StandardHttpRequest(const URI& uri, HttpMethod method) :
+ HttpRequest(uri, method),
+ bodyStream(nullptr),
+ m_responseStreamFactory()
+{
+ if(IsDefaultPort(uri))
+ {
+ StandardHttpRequest::SetHeaderValue(HOST_HEADER, uri.GetAuthority());
+ }
+ else
+ {
+ Aws::StringStream host;
+ host << uri.GetAuthority() << ":" << uri.GetPort();
+ StandardHttpRequest::SetHeaderValue(HOST_HEADER, host.str());
+ }
+}
+
+HeaderValueCollection StandardHttpRequest::GetHeaders() const
+{
+ HeaderValueCollection headers;
+
+ for (HeaderValueCollection::const_iterator iter = headerMap.begin(); iter != headerMap.end(); ++iter)
+ {
+ headers.emplace(HeaderValuePair(iter->first, iter->second));
+ }
+
+ return headers;
+}
+
+const Aws::String& StandardHttpRequest::GetHeaderValue(const char* headerName) const
+{
+ auto iter = headerMap.find(headerName);
+ assert (iter != headerMap.end());
+ return iter->second;
+}
+
+void StandardHttpRequest::SetHeaderValue(const char* headerName, const Aws::String& headerValue)
+{
+ headerMap[StringUtils::ToLower(headerName)] = StringUtils::Trim(headerValue.c_str());
+}
+
+void StandardHttpRequest::SetHeaderValue(const Aws::String& headerName, const Aws::String& headerValue)
+{
+ headerMap[StringUtils::ToLower(headerName.c_str())] = StringUtils::Trim(headerValue.c_str());
+}
+
+void StandardHttpRequest::DeleteHeader(const char* headerName)
+{
+ headerMap.erase(StringUtils::ToLower(headerName));
+}
+
+bool StandardHttpRequest::HasHeader(const char* headerName) const
+{
+ return headerMap.find(StringUtils::ToLower(headerName)) != headerMap.end();
+}
+
+int64_t StandardHttpRequest::GetSize() const
+{
+ int64_t size = 0;
+
+ std::for_each(headerMap.cbegin(), headerMap.cend(), [&](const HeaderValueCollection::value_type& kvPair){ size += kvPair.first.length(); size += kvPair.second.length(); });
+
+ return size;
+}
+
+const Aws::IOStreamFactory& StandardHttpRequest::GetResponseStreamFactory() const
+{
+ return m_responseStreamFactory;
+}
+
+void StandardHttpRequest::SetResponseStreamFactory(const Aws::IOStreamFactory& factory)
+{
+ m_responseStreamFactory = factory;
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp
new file mode 100644
index 0000000000..92d7a062b6
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/standard/StandardHttpResponse.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/http/standard/StandardHttpResponse.h>
+
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/memory/AWSMemory.h>
+
+#include <istream>
+
+using namespace Aws::Http;
+using namespace Aws::Http::Standard;
+using namespace Aws::Utils;
+
+
+HeaderValueCollection StandardHttpResponse::GetHeaders() const
+{
+ HeaderValueCollection headerValueCollection;
+
+ for (Aws::Map<Aws::String, Aws::String>::const_iterator iter = headerMap.begin(); iter != headerMap.end(); ++iter)
+ {
+ headerValueCollection.emplace(HeaderValuePair(iter->first, iter->second));
+ }
+
+ return headerValueCollection;
+}
+
+bool StandardHttpResponse::HasHeader(const char* headerName) const
+{
+ return headerMap.find(StringUtils::ToLower(headerName)) != headerMap.end();
+}
+
+const Aws::String& StandardHttpResponse::GetHeader(const Aws::String& headerName) const
+{
+ Aws::Map<Aws::String, Aws::String>::const_iterator foundValue = headerMap.find(StringUtils::ToLower(headerName.c_str()));
+ return foundValue->second;
+}
+
+void StandardHttpResponse::AddHeader(const Aws::String& headerName, const Aws::String& headerValue)
+{
+ headerMap[StringUtils::ToLower(headerName.c_str())] = headerValue;
+}
+
+