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/http/curl | |
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/http/curl')
-rw-r--r-- | contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHandleContainer.cpp | 5 | ||||
-rw-r--r-- | contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp | 108 |
2 files changed, 101 insertions, 12 deletions
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 index 1a965cd795..a6684c640a 100644 --- 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 @@ -43,7 +43,7 @@ CURL* CurlHandleContainer::AcquireCurlHandle() } CURL* handle = m_handleContainer.Acquire(); - AWS_LOGSTREAM_INFO(CURL_HANDLE_CONTAINER_TAG, "Connection has been released. Continuing."); + AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Connection has been released. Continuing."); AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Returning connection handle " << handle); return handle; } @@ -52,6 +52,9 @@ void CurlHandleContainer::ReleaseCurlHandle(CURL* handle) { if (handle) { +#if LIBCURL_VERSION_NUM >= 0x074D00 // 7.77.0 + curl_easy_setopt(handle, CURLOPT_COOKIEFILE, NULL); // workaround a mem leak on curl +#endif curl_easy_reset(handle); SetDefaultOptionsOnHandle(handle); AWS_LOGSTREAM_DEBUG(CURL_HANDLE_CONTAINER_TAG, "Releasing curl handle " << handle); 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 index 95132f5df0..0f64b15062 100644 --- 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 @@ -7,9 +7,12 @@ #include <aws/core/http/HttpRequest.h> #include <aws/core/http/standard/StandardHttpResponse.h> #include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/HashingUtils.h> #include <aws/core/utils/logging/LogMacros.h> #include <aws/core/utils/ratelimiter/RateLimiterInterface.h> #include <aws/core/utils/DateTime.h> +#include <aws/core/utils/crypto/Hash.h> +#include <aws/core/utils/Outcome.h> #include <aws/core/monitoring/HttpClientMetrics.h> #include <cassert> #include <algorithm> @@ -146,17 +149,34 @@ struct CurlReadCallbackContext m_client(client), m_curlHandle(curlHandle), m_rateLimiter(limiter), - m_request(request) + m_request(request), + m_chunkEnd(false) {} const CurlHttpClient* m_client; CURL* m_curlHandle; Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter; HttpRequest* m_request; + bool m_chunkEnd; }; static const char* CURL_HTTP_CLIENT_TAG = "CurlHttpClient"; +static int64_t GetContentLengthFromHeader(CURL* connectionHandle, + bool& hasContentLength) { +#if LIBCURL_VERSION_NUM >= 0x073700 // 7.55.0 + curl_off_t contentLength = {}; + CURLcode res = curl_easy_getinfo( + connectionHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &contentLength); +#else + double contentLength = {}; + CURLcode res = curl_easy_getinfo( + connectionHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength); +#endif + hasContentLength = (res == CURLE_OK) && (contentLength != -1); + return hasContentLength ? static_cast<int64_t>(contentLength) : -1; +} + static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata) { if (ptr) @@ -176,8 +196,13 @@ static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata) context->m_rateLimiter->ApplyAndPayForCost(static_cast<int64_t>(sizeToWrite)); } + for (const auto& hashIterator : context->m_request->GetResponseValidationHashes()) + { + hashIterator.second->Update(reinterpret_cast<unsigned char*>(ptr), sizeToWrite); + } + response->GetResponseBody().write(ptr, static_cast<std::streamsize>(sizeToWrite)); - if (context->m_request->IsEventStreamRequest()) + if (context->m_request->IsEventStreamRequest() && !response->HasHeader(Aws::Http::X_AMZN_ERROR_TYPE)) { response->GetResponseBody().flush(); } @@ -214,8 +239,7 @@ static size_t WriteHeader(char* ptr, size_t size, size_t nmemb, void* userdata) return 0; } - -static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata) +static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata, bool isStreaming) { CurlReadCallbackContext* context = reinterpret_cast<CurlReadCallbackContext*>(userdata); if(context == nullptr) @@ -232,10 +256,20 @@ static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata) HttpRequest* request = context->m_request; const std::shared_ptr<Aws::IOStream>& ioStream = request->GetContentBody(); - const size_t amountToRead = size * nmemb; + size_t amountToRead = size * nmemb; + bool isAwsChunked = request->HasHeader(Aws::Http::CONTENT_ENCODING_HEADER) && + request->GetHeaderValue(Aws::Http::CONTENT_ENCODING_HEADER) == Aws::Http::AWS_CHUNKED_VALUE; + // aws-chunk = hex(chunk-size) + CRLF + chunk-data + CRLF + // Needs to reserve bytes of sizeof(hex(chunk-size)) + sizeof(CRLF) + sizeof(CRLF) + if (isAwsChunked) + { + Aws::String amountToReadHexString = Aws::Utils::StringUtils::ToHexString(amountToRead); + amountToRead -= (amountToReadHexString.size() + 4); + } + if (ioStream != nullptr && amountToRead > 0) { - if (request->IsEventStreamRequest()) + if (isStreaming) { if (ioStream->readsome(ptr, amountToRead) == 0 && !ioStream->eof()) { @@ -247,6 +281,39 @@ static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata) ioStream->read(ptr, amountToRead); } size_t amountRead = static_cast<size_t>(ioStream->gcount()); + + if (isAwsChunked) + { + if (amountRead > 0) + { + if (request->GetRequestHash().second != nullptr) + { + request->GetRequestHash().second->Update(reinterpret_cast<unsigned char*>(ptr), amountRead); + } + + Aws::String hex = Aws::Utils::StringUtils::ToHexString(amountRead); + memmove(ptr + hex.size() + 2, ptr, amountRead); + memmove(ptr + hex.size() + 2 + amountRead, "\r\n", 2); + memmove(ptr, hex.c_str(), hex.size()); + memmove(ptr + hex.size(), "\r\n", 2); + amountRead += hex.size() + 4; + } + else if (!context->m_chunkEnd) + { + Aws::StringStream chunkedTrailer; + chunkedTrailer << "0\r\n"; + if (request->GetRequestHash().second != nullptr) + { + chunkedTrailer << "x-amz-checksum-" << request->GetRequestHash().first << ":" + << HashingUtils::Base64Encode(request->GetRequestHash().second->GetHash().GetResult()) << "\r\n"; + } + chunkedTrailer << "\r\n"; + amountRead = chunkedTrailer.str().size(); + memcpy(ptr, chunkedTrailer.str().c_str(), amountRead); + context->m_chunkEnd = true; + } + } + auto& sentHandler = request->GetDataSentEventHandler(); if (sentHandler) { @@ -264,6 +331,14 @@ static size_t ReadBody(char* ptr, size_t size, size_t nmemb, void* userdata) return 0; } +static size_t ReadBodyStreaming(char* ptr, size_t size, size_t nmemb, void* userdata) { + return ReadBody(ptr, size, nmemb, userdata, true); +} + +static size_t ReadBodyFunc(char* ptr, size_t size, size_t nmemb, void* userdata) { + return ReadBody(ptr, size, nmemb, userdata, false); +} + static size_t SeekBody(void* userdata, curl_off_t offset, int origin) { CurlReadCallbackContext* context = reinterpret_cast<CurlReadCallbackContext*>(userdata); @@ -358,7 +433,11 @@ void SetOptCodeForHttpMethod(CURL* requestHandle, const std::shared_ptr<HttpRequ } else { +#if LIBCURL_VERSION_NUM >= 0x070c01 // 7.12.1 + curl_easy_setopt(requestHandle, CURLOPT_UPLOAD, 1L); +#else curl_easy_setopt(requestHandle, CURLOPT_PUT, 1L); +#endif } break; case HttpMethod::HTTP_HEAD: @@ -579,6 +658,9 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr< curl_easy_setopt(connectionHandle, CURLOPT_CAINFO, m_caFile.c_str()); } + // enable the cookie engine without reading any initial cookies. + curl_easy_setopt(connectionHandle, CURLOPT_COOKIEFILE, ""); + // 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); @@ -664,12 +746,13 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr< if (request->GetContentBody()) { - curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBody); + curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBodyFunc); curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &readContext); curl_easy_setopt(connectionHandle, CURLOPT_SEEKFUNCTION, SeekBody); curl_easy_setopt(connectionHandle, CURLOPT_SEEKDATA, &readContext); - if (request->IsEventStreamRequest()) + if (request->IsEventStreamRequest() && !response->HasHeader(Aws::Http::X_AMZN_ERROR_TYPE)) { + curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, ReadBodyStreaming); curl_easy_setopt(connectionHandle, CURLOPT_NOPROGRESS, 0L); #if LIBCURL_VERSION_NUM >= 0x072000 // 7.32.0 curl_easy_setopt(connectionHandle, CURLOPT_XFERINFOFUNCTION, CurlProgressCallback); @@ -714,15 +797,18 @@ std::shared_ptr<HttpResponse> CurlHttpClient::MakeRequest(const std::shared_ptr< AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned content type " << contentType); } + bool hasContentLength = false; + int64_t contentLength = + GetContentLengthFromHeader(connectionHandle, hasContentLength); + if (request->GetMethod() != HttpMethod::HTTP_HEAD && writeContext.m_client->IsRequestProcessingEnabled() && - response->HasHeader(Aws::Http::CONTENT_LENGTH_HEADER)) + hasContentLength) { - 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) + if (contentLength != numBytesResponseReceived) { response->SetClientErrorType(CoreErrors::NETWORK_CONNECTION); response->SetClientErrorMessage("Response body length doesn't match the content-length header."); |