From 5e3cd1fb01118599a3e6a4420e2939901ea42d08 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Mon, 18 Oct 2021 15:01:00 -0700 Subject: [PATCH] Adding a static-blocking libcurl transport adapter (#2948) * static libcurl transport adapter * ignore cspell * updates to implementation --- sdk/core/azure-core/CHANGELOG.md | 4 +- sdk/core/azure-core/CMakeLists.txt | 5 +- .../azure/core/http/static_curl_transport.hpp | 127 +++++ .../azure-core/src/http/curl/static_curl.cpp | 496 ++++++++++++++++++ .../test/ut/transport_adapter_base_test.hpp | 17 +- .../transport_adapter_implementation_test.cpp | 11 +- 6 files changed, 645 insertions(+), 15 deletions(-) create mode 100644 sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp create mode 100644 sdk/core/azure-core/src/http/curl/static_curl.cpp diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index 02cf6bacd..7b5898bdf 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -4,6 +4,8 @@ ### Features Added +- Add the static libcurl transport adapter. + ### Breaking Changes ### Bugs Fixed @@ -293,7 +295,7 @@ Thank you to our developer community members who helped to make Azure Core bette ### Acknowledgments Thank you to our developer community members who helped to make Azure Core better with their contributions to this release: - + - Gabor Gyimesi _([GitHub](https://github.com/lordgamez))_ - Marcelo Juchem _([GitHub](https://github.com/juchem))_ - `ku-sourav` _([GitHub](https://github.com/ku-sourav))_ diff --git a/sdk/core/azure-core/CMakeLists.txt b/sdk/core/azure-core/CMakeLists.txt index bb6598ab4..f47afa75d 100644 --- a/sdk/core/azure-core/CMakeLists.txt +++ b/sdk/core/azure-core/CMakeLists.txt @@ -40,8 +40,11 @@ if(BUILD_TRANSPORT_CURL) src/http/curl/curl_connection_private.hpp src/http/curl/curl_session_private.hpp src/http/curl/curl.cpp + src/http/curl/static_curl.cpp ) - SET(CURL_TRANSPORT_ADAPTER_INC inc/azure/core/http/curl_transport.hpp) + SET(CURL_TRANSPORT_ADAPTER_INC + inc/azure/core/http/curl_transport.hpp + inc/azure/core/http/static_curl_transport.hpp) endif() if(BUILD_TRANSPORT_WINHTTP) SET(WIN_TRANSPORT_ADAPTER_SRC src/http/winhttp/win_http_transport.cpp) diff --git a/sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp b/sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp new file mode 100644 index 000000000..0adafe35a --- /dev/null +++ b/sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +/** + * @file + * @brief #Azure::Core::Http::HttpTransport static implementation using libcurl won't produce real + * response streams. The HTTP responses are first statically downloaded within the transport + * adapter. + * + * @remark This transport adapater is less efficient than the non-static version. Use this + * implementation where performance ( memory and time ) is not a concern. + */ + +#pragma once + +#include "azure/core/context.hpp" +#include "azure/core/http/http.hpp" +#include "azure/core/http/transport.hpp" + +namespace Azure { namespace Core { namespace Http { + + /** + * @brief The available options to set libcurl SSL options. + * + * @remark The SDK will map the enum option to libcurl's specific option. See more info here: + * https://curl.haxx.se/libcurl/c/CURLOPT_SSL_OPTIONS.html + * + */ + struct StaticCurlTransportSslOptions final + { + /** + * @brief This option can enable the revocation list check. + * + * @remark Libcurl does revocation list check by default for SSL backends that supports this + * feature. However, the Azure SDK overrides libcurl's behavior and disables the revocation list + * check by default. + * + */ + bool EnableCertificateRevocationListCheck = false; + }; + + /** + * @brief Set the libcurl connection options like a proxy and CA path. + */ + struct StaticCurlTransportOptions final + { + /** + * @brief The string for the proxy is passed directly to the libcurl handle without any parsing + * + * @remark No validation for the string is done by the Azure SDK. More about this option: + * https://curl.haxx.se/libcurl/c/CURLOPT_PROXY.html. + * + * @remark The default value is an empty string (no proxy). + * + */ + std::string Proxy; + /** + * @brief The string for the certificate authenticator is sent to libcurl handle directly. + * + * @remark The Azure SDK will not check if the path is valid or not. + * + * @remark The default is the built-in system specific path. More about this option: + * https://curl.haxx.se/libcurl/c/CURLOPT_CAINFO.html + * + */ + std::string CAInfo; + /** + * @brief All HTTP requests will keep the connection channel open to the service. + * + * @remark The channel might be closed by the server if the server response has an error code. + * A connection won't be re-used if it is abandoned in the middle of an operation. + * operation. + * + * @remark This option is managed directly by the Azure SDK. No option is set for the curl + * handle. It is `true` by default. + */ + bool HttpKeepAlive = true; + /** + * @brief This option determines whether libcurl verifies the authenticity of the peer's + * certificate. + * + * @remark The default value is `true`. More about this option: + * https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html + * + */ + bool SslVerifyPeer = true; + + /** + * @brief Define the SSL options for the libcurl handle. + * + * @remark See more info here: https://curl.haxx.se/libcurl/c/CURLOPT_SSL_OPTIONS.html. + * The default option is all options `false`. + * + */ + StaticCurlTransportSslOptions SslOptions; + }; + + /** + * @brief Concrete implementation of an HTTP Transport that uses libcurl. + */ + class StaticCurlTransport final : public HttpTransport { + private: + StaticCurlTransportOptions m_options; + + public: + /** + * @brief Construct a new CurlTransport object. + * + * @param options Optional parameter to override the default options. + */ + StaticCurlTransport(StaticCurlTransportOptions const& options = StaticCurlTransportOptions()) + : m_options(options) + { + } + + /** + * @brief Implements interface to send an HTTP Request and produce an HTTP RawResponse + * + * @param request an HTTP Request to be send. + * @param context A context to control the request lifetime. + * + * @return unique ptr to an HTTP RawResponse. + */ + std::unique_ptr Send(Request& request, Context const& context) override; + }; + +}}} // namespace Azure::Core::Http diff --git a/sdk/core/azure-core/src/http/curl/static_curl.cpp b/sdk/core/azure-core/src/http/curl/static_curl.cpp new file mode 100644 index 000000000..dd7ac279c --- /dev/null +++ b/sdk/core/azure-core/src/http/curl/static_curl.cpp @@ -0,0 +1,496 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include "azure/core/http/policies/policy.hpp" +#include "azure/core/http/static_curl_transport.hpp" +#include "azure/core/internal/diagnostics/log.hpp" + +#include + +#if defined(_MSC_VER) +// C6101 : Returning uninitialized memory '*Mtu'->libcurl calling WSAGetIPUserMtu from WS2tcpip.h +#pragma warning(push) +#pragma warning(disable : 6101) +#endif + +#include + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +using Azure::Core::Context; +using Azure::Core::Http::HttpStatusCode; +using Azure::Core::Http::RawResponse; +using Azure::Core::Http::Request; +using Azure::Core::Http::TransportException; + +namespace { +constexpr static const char* FailedToGetNewConnectionTemplate + = "[static impl] Fail to get a new connection for: "; + +constexpr static const int HttpWordLen = 4; + +template +#if defined(_MSC_VER) +#pragma warning(push) +// C26812: The enum type 'CURLoption' is un-scoped. Prefer 'enum class' over 'enum' (Enum.3) +#pragma warning(disable : 26812) +#endif +inline bool SetStaticLibcurlOption(CURL* handle, CURLoption option, T value, CURLcode* outError) +{ + *outError = curl_easy_setopt(handle, option, value); + return *outError == CURLE_OK; +} +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +class StaticCurlImpl final : public Azure::Core::IO::BodyStream { +private: + CURL* m_libcurlHandle; + struct curl_slist* m_headerHandle = NULL; + Azure::Core::Http::StaticCurlTransportOptions m_options; + std::unique_ptr m_response = nullptr; + std::vector m_responseData; + std::vector m_sendBuffer; + std::unique_ptr m_responseStream; + bool m_isTransferEncodingChunked = false; + + // Returns the next token from `*begin` to the next separator parsed as T + // *begin gets updated to the next token after the separator. + // use the last param to change the return type to other than int + template + static T GetNextToken( + char const** begin, + char const* const last, + char const separator, + std::function mutator + = [](std::string const& value) { return std::stoi(value); }) + { + auto start = *begin; + auto end = std::find(start, last, separator); + // Move the original ptr to one place after the separator + *begin = end + 1; + return mutator(std::string(start, end)); + } + + static std::unique_ptr CreateHTTPResponse( + char const* const begin, + char const* const last) + { + // set response code, HTTP version and reason phrase (i.e. HTTP/1.1 200 OK) + auto start = begin + HttpWordLen + 1; // HTTP = 4, / = 1, moving to 5th place for version + auto majorVersion = GetNextToken(&start, last, '.'); + auto minorVersion = GetNextToken(&start, last, ' '); + auto statusCode = GetNextToken(&start, last, ' '); + auto reasonPhrase = GetNextToken( + &start, last, '\r', [](std::string const& value) { return value; }); + + // allocate the instance of response to heap with shared ptr + // So this memory gets delegated outside CurlTransport as a shared_ptr so memory will be + // eventually released + return std::make_unique( + static_cast(majorVersion), + static_cast(minorVersion), + HttpStatusCode(statusCode), + reasonPhrase); + } + + static void StaticSetHeader( + Azure::Core::Http::RawResponse& response, + char const* const first, + char const* const last) + { + // get name and value from header + auto start = first; + auto end = std::find(start, last, ':'); + + if ((last - first) == 2 && *start == '\r' && *(start + 1) == '\n') + { + // Libcurl gives the end of headers as `\r\n`, we just ignore it + return; + } + + if (end == last) + { + throw std::invalid_argument("Invalid header. No delimiter ':' found."); + } + + // Always toLower() headers + auto headerName = Azure::Core::_internal::StringExtensions::ToLower(std::string(start, end)); + start = end + 1; // start value + while (start < last && (*start == ' ' || *start == '\t')) + { + ++start; + } + + end = std::find(start, last, '\r'); + auto headerValue = std::string(start, end); // remove \r + + response.SetHeader(headerName, headerValue); + } + + /*************************** CALL BACKS */ + + /** + * @brief This is the function that curl will use to write response into a user provider span + * Function receives the size of the response and must return this same number, otherwise it is + * consider that function failed + * + * @param contents response data from Curl response + * @param size size of the curl response data + * @param nmemb number of blocks in response + * @param userp this represent a structure linked to response by us before + * @return int + */ + static size_t ReceiveInitialResponse(char* contents, size_t size, size_t nmemb, void* userp) + { + size_t const expectedSize = size * nmemb; + std::unique_ptr* rawResponse = static_cast*>(userp); + + // First response + if (*rawResponse == nullptr) + { + // parse header to get init data + *rawResponse = CreateHTTPResponse(contents, contents + expectedSize); + } + else + { + StaticSetHeader(*(*rawResponse), contents, contents + expectedSize); + } + + // This callback needs to return the response size or curl will consider it as it failed + return expectedSize; + } + + static size_t ReceiveData(void* contents, size_t size, size_t nmemb, void* userp) + { + size_t const expectedSize = size * nmemb; + std::vector& rawResponse = *(static_cast*>(userp)); + uint8_t* data = static_cast(contents); + + rawResponse.insert(rawResponse.end(), data, data + expectedSize); + + // This callback needs to return the response size or curl will consider it as it failed + return expectedSize; + } + + static size_t UploadData(void* dst, size_t size, size_t nmemb, void* userdata) + { + // Calculate the size of the *dst buffer + auto destSize = nmemb * size; + Azure::Core::IO::BodyStream* uploadStream = static_cast(userdata); + + // Terminate the upload if the destination buffer is too small + if (destSize < 1) + { + throw Azure::Core::Http::TransportException("Not enough size to continue to upload data."); + } + + // Copy as many bytes as possible from the stream to libcurl's destination buffer + return uploadStream->Read(static_cast(dst), destSize); + } + + size_t OnRead(uint8_t* buffer, size_t count, Azure::Core::Context const& context) override + { + return m_responseStream->Read(buffer, count, context); + } + +public: + StaticCurlImpl( + Azure::Core::Http::StaticCurlTransportOptions const& options + = Azure::Core::Http::StaticCurlTransportOptions()) + : m_options(options) + { + // ****************************************************************** + // *************************************************** INIT ****** + // ****************************************************************** + m_libcurlHandle = curl_easy_init(); + if (!m_libcurlHandle) + { + throw Azure::Core::Http::TransportException("Failed to create libcurl handle"); + } + } + + ~StaticCurlImpl() + { + if (m_headerHandle) + { + curl_slist_free_all(m_headerHandle); + } + + if (m_libcurlHandle) + { + curl_easy_cleanup(m_libcurlHandle); + } + } + + std::unique_ptr Send(Request& request, Context const& context) + { + context.ThrowIfCancelled(); + uint16_t port = request.GetUrl().GetPort(); + std::string const& host = request.GetUrl().GetScheme() + request.GetUrl().GetHost() + + (port != 0 ? std::to_string(port) : ""); + + // ****************************************************************** + // *************************************************** SET UP ****** + // ****************************************************************** + CURLcode result; + // Libcurl setup before open connection (url, connect_only, timeout) + if (!SetStaticLibcurlOption( + m_libcurlHandle, CURLOPT_URL, request.GetUrl().GetAbsoluteUrl().data(), &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". " + std::string(curl_easy_strerror(result))); + } + if (port != 0 && !SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_PORT, port, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". " + std::string(curl_easy_strerror(result))); + } + if (!m_options.Proxy.empty()) + { + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_PROXY, m_options.Proxy.c_str(), &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set proxy to:" + m_options.Proxy + + ". " + std::string(curl_easy_strerror(result))); + } + } + if (!m_options.CAInfo.empty()) + { + if (!SetStaticLibcurlOption( + m_libcurlHandle, CURLOPT_CAINFO, m_options.CAInfo.c_str(), &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set CA cert to:" + + m_options.CAInfo + ". " + std::string(curl_easy_strerror(result))); + } + } + long sslOption = 0; + if (!m_options.SslOptions.EnableCertificateRevocationListCheck) + { + sslOption |= CURLSSLOPT_NO_REVOKE; + } + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_SSL_OPTIONS, sslOption, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set ssl options to long bitmask:" + + std::to_string(sslOption) + ". " + std::string(curl_easy_strerror(result))); + } + if (!m_options.SslVerifyPeer) + { + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_SSL_VERIFYPEER, 0L, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to disable ssl verify peer." + ". " + + std::string(curl_easy_strerror(result))); + } + } + + // headers sep-up + auto const& headers = request.GetHeaders(); + if (headers.size() > 0) + { + for (auto const& header : headers) + { + auto newHandle + = curl_slist_append(m_headerHandle, (header.first + ":" + header.second).c_str()); + if (newHandle == NULL) + { + throw Azure::Core::Http::TransportException("Failing creating header list for libcurl"); + } + m_headerHandle = newHandle; + } + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_HTTPHEADER, m_headerHandle, &result)) + { + throw Azure::Core::Http::TransportException(". Failed to set header."); + } + } + + // Callback set up + if (!SetStaticLibcurlOption( + m_libcurlHandle, CURLOPT_HEADERFUNCTION, ReceiveInitialResponse, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set headers callback." + ". " + + std::string(curl_easy_strerror(result))); + } + + if (!SetStaticLibcurlOption( + m_libcurlHandle, CURLOPT_HEADERDATA, static_cast(&m_response), &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set headers data." + ". " + + std::string(curl_easy_strerror(result))); + } + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_WRITEFUNCTION, ReceiveData, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set data callback." + ". " + + std::string(curl_easy_strerror(result))); + } + + if (!SetStaticLibcurlOption( + m_libcurlHandle, CURLOPT_WRITEDATA, static_cast(&m_responseData), &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set write data." + ". " + + std::string(curl_easy_strerror(result))); + } + + // Method set up + auto const& method = request.GetMethod(); + if (method == Azure::Core::Http::HttpMethod::Delete) + { + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE", &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set DELETE Method." + ". " + + std::string(curl_easy_strerror(result))); + } + } + else if (method == Azure::Core::Http::HttpMethod::Patch) + { + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH", &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set PATCH Method." + ". " + + std::string(curl_easy_strerror(result))); + } + } + else if (method == Azure::Core::Http::HttpMethod::Head) + { + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_NOBODY, 1L, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set HEAD Method." + ". " + + std::string(curl_easy_strerror(result))); + } + } + else if (method == Azure::Core::Http::HttpMethod::Post) + { + // Adds special header "Expect:" for libcurl to avoid sending only headers to server and wait + // for a 100 Continue response before sending a PUT method + auto newHandle = curl_slist_append(m_headerHandle, "Expect:"); + if (newHandle == NULL) + { + throw Azure::Core::Http::TransportException("Failing adding Expect header for POST"); + } + m_headerHandle = newHandle; + + m_sendBuffer = request.GetBodyStream()->ReadToEnd(); + m_sendBuffer.emplace_back('\0'); // the body is expected to be null terminated + if (!SetStaticLibcurlOption( + m_libcurlHandle, + CURLOPT_POSTFIELDS, + reinterpret_cast(m_sendBuffer.data()), + &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set POST Data." + ". " + + std::string(curl_easy_strerror(result))); + } + } + else if (method == Azure::Core::Http::HttpMethod::Put) + { + // As of CURL 7.12.1 CURLOPT_PUT is deprecated. PUT requests should be made using + // CURLOPT_UPLOAD + + // Adds special header "Expect:" for libcurl to avoid sending only headers to server and wait + // for a 100 Continue response before sending a PUT method + auto newHandle = curl_slist_append(m_headerHandle, "Expect:"); + if (newHandle == NULL) + { + throw Azure::Core::Http::TransportException("Failing adding Expect header for POST"); + } + m_headerHandle = newHandle; + + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_UPLOAD, 1L, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set Curl handle to PUT mode" + + ". " + std::string(curl_easy_strerror(result))); + } + + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_READFUNCTION, UploadData, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set Upload callback" + ". " + + std::string(curl_easy_strerror(result))); + } + + auto uploadStream = request.GetBodyStream(); + if (!SetStaticLibcurlOption( + m_libcurlHandle, CURLOPT_READDATA, static_cast(uploadStream), &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set Upload body Stream" + ". " + + std::string(curl_easy_strerror(result))); + } + if (!SetStaticLibcurlOption( + m_libcurlHandle, + CURLOPT_INFILESIZE, + static_cast(uploadStream->Length()), + &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". Failed to set Upload body Stream Size" + + ". " + std::string(curl_easy_strerror(result))); + } + } + + // ****************************************************************** + // *************************************************** PERFORM & RECEIVE ****** + // ****************************************************************** + // curl_easy_perform will block the program until all the response is received + auto performResult = curl_easy_perform(m_libcurlHandle); + if (performResult != CURLE_OK) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + ". " + + std::string(curl_easy_strerror(performResult))); + } + + // At this point, libcurl has read all the response from server successfully and the response + // was written to `m_responseData`. Let's init a memoryBodyStream to enable this class to bahave + // as a bodyStream. + m_responseStream = std::make_unique(m_responseData); + + auto const& responseHeaders = m_response->GetHeaders(); + auto isTransferEncodingHeaderInResponse = responseHeaders.find("transfer-encoding"); + if (isTransferEncodingHeaderInResponse != responseHeaders.end()) + { + // if `chunked` is found inside the transfer-encoding, we activate the + // isTransferEncodingChunked flag. The static-libcurl implementation handles downloading a + // chunked response. The entire response is already downloaded, so we will just use the header + // to modify the way the body stream behaves so it acts as an unknown-size memory stream. + auto headerValue = isTransferEncodingHeaderInResponse->second; + m_isTransferEncodingChunked = headerValue.find("chunked") != std::string::npos; + } + + // ****************************************************************** + // *************************************************** Return response ****** + // ****************************************************************** + return std::move(m_response); + } + + int64_t Length() const override + { + return m_isTransferEncodingChunked ? -1 : m_responseStream->Length(); + } + + void Rewind() override { return m_responseStream->Rewind(); } +}; +} // namespace + +std::unique_ptr Azure::Core::Http::StaticCurlTransport::Send( + Request& request, + Context const& context) +{ + auto client = std::make_unique(m_options); + auto response = client->Send(request, context); + response->SetBodyStream(std::move(client)); + return response; +} diff --git a/sdk/core/azure-core/test/ut/transport_adapter_base_test.hpp b/sdk/core/azure-core/test/ut/transport_adapter_base_test.hpp index 0dd22ab74..c1aa59a78 100644 --- a/sdk/core/azure-core/test/ut/transport_adapter_base_test.hpp +++ b/sdk/core/azure-core/test/ut/transport_adapter_base_test.hpp @@ -80,19 +80,14 @@ namespace Azure { namespace Core { namespace Test { // Befor each test, create pipeline virtual void SetUp() override { + std::vector> retryPolicies; std::vector> policies; - Azure::Core::Http::Policies::RetryOptions opt; - opt.RetryDelay = std::chrono::milliseconds(10); - // Retry policy will help to prevent server-occasionally-errors - policies.push_back( - std::make_unique(opt)); - // Will get transport policy options from test param - // auto param = GetParam(); - policies.push_back(std::make_unique( - GetParam().TransportAdapter)); - - m_pipeline = std::make_unique(policies); + Azure::Core::_internal::ClientOptions op; + op.Retry.RetryDelay = std::chrono::milliseconds(10); + op.Transport = GetParam().TransportAdapter; + m_pipeline = std::make_unique( + op, "TransportTest", "X.X", std::move(retryPolicies), std::move(policies)); } static void CheckBodyFromBuffer( diff --git a/sdk/core/azure-core/test/ut/transport_adapter_implementation_test.cpp b/sdk/core/azure-core/test/ut/transport_adapter_implementation_test.cpp index 85117bec7..9d1ee1356 100644 --- a/sdk/core/azure-core/test/ut/transport_adapter_implementation_test.cpp +++ b/sdk/core/azure-core/test/ut/transport_adapter_implementation_test.cpp @@ -8,6 +8,7 @@ #if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER) #include "azure/core/http/curl_transport.hpp" +#include "azure/core/http/static_curl_transport.hpp" #endif #if defined(BUILD_TRANSPORT_WINHTTP_ADAPTER) @@ -54,7 +55,10 @@ namespace Azure { namespace Core { namespace Test { TransportAdapter, testing::Values( GetTransportOptions("winHttp", std::make_shared()), - GetTransportOptions("libCurl", std::make_shared())), + GetTransportOptions("libCurl", std::make_shared()), + GetTransportOptions( + "staticLibCurl", + std::make_shared())), GetSuffix); #elif defined(BUILD_TRANSPORT_WINHTTP_ADAPTER) @@ -72,7 +76,10 @@ namespace Azure { namespace Core { namespace Test { Test, TransportAdapter, testing::Values( - GetTransportOptions("libCurl", std::make_shared())), + GetTransportOptions("libCurl", std::make_shared()), + GetTransportOptions( + "staticLibCurl", + std::make_shared())), GetSuffix); #else /* Custom adapter. Not adding tests */