diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index b79b2cf6e..cf790f7ee 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -3,10 +3,13 @@ ## 1.5.0-beta.1 (Unreleased) ### Features Added + - When a `RequestFailedException` exception is thrown, the `what()` method now includes information about the HTTP request which failed. ### Other Changes +- Improve output message for `Azure::Core::Http::TransportException`. + ## 1.4.0 (2022-03-03) ### Features Added diff --git a/sdk/core/azure-core/src/http/curl/curl.cpp b/sdk/core/azure-core/src/http/curl/curl.cpp index e16c4b454..ade2629e5 100644 --- a/sdk/core/azure-core/src/http/curl/curl.cpp +++ b/sdk/core/azure-core/src/http/curl/curl.cpp @@ -1246,9 +1246,10 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo bool resetPool) { uint16_t port = request.GetUrl().GetPort(); - std::string const& host = request.GetUrl().GetScheme() + request.GetUrl().GetHost() - + (port != 0 ? std::to_string(port) : ""); - std::string const connectionKey = GetConnectionKey(host, options); + // Generate a display name for the host being connected to + std::string const& hostDisplayName = request.GetUrl().GetScheme() + "://" + + request.GetUrl().GetHost() + (port != 0 ? ":" + std::to_string(port) : ""); + std::string const connectionKey = GetConnectionKey(hostDisplayName, options); { decltype(CurlConnectionPool::g_curlConnectionPool @@ -1303,7 +1304,7 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!newHandle) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". " + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". " + std::string("curl_easy_init returned Null")); } CURLcode result; @@ -1312,21 +1313,21 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_URL, request.GetUrl().GetAbsoluteUrl().data(), &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". " + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". " + std::string(curl_easy_strerror(result))); } if (port != 0 && !SetLibcurlOption(newHandle, CURLOPT_PORT, port, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". " + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". " + std::string(curl_easy_strerror(result))); } if (!SetLibcurlOption(newHandle, CURLOPT_CONNECT_ONLY, 1L, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". " + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". " + std::string(curl_easy_strerror(result))); } @@ -1336,7 +1337,7 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_TIMEOUT, 60L * 60L * 24L, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". " + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". " + std::string(curl_easy_strerror(result))); } @@ -1345,7 +1346,7 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_CONNECTTIMEOUT_MS, options.ConnectionTimeout, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". Fail setting connect timeout to: " + std::to_string(options.ConnectionTimeout.count()) + " ms. " + std::string(curl_easy_strerror(result))); @@ -1360,8 +1361,9 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_PROXY, options.Proxy.c_str(), &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". Failed to set proxy to:" - + options.Proxy + ". " + std::string(curl_easy_strerror(result))); + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + + ". Failed to set proxy to:" + options.Proxy + ". " + + std::string(curl_easy_strerror(result))); } } @@ -1370,8 +1372,9 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_CAINFO, options.CAInfo.c_str(), &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". Failed to set CA cert to:" - + options.CAInfo + ". " + std::string(curl_easy_strerror(result))); + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + + ". Failed to set CA cert to:" + options.CAInfo + ". " + + std::string(curl_easy_strerror(result))); } } @@ -1384,7 +1387,7 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_SSL_OPTIONS, sslOption, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". Failed to set ssl options to long bitmask:" + std::to_string(sslOption) + ". " + std::string(curl_easy_strerror(result))); } @@ -1394,7 +1397,7 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_SSL_VERIFYPEER, 0L, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". Failed to disable ssl verify peer. " + std::string(curl_easy_strerror(result))); } } @@ -1404,7 +1407,7 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_NOSIGNAL, 1L, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". Failed to set NOSIGNAL option for libcurl. " + std::string(curl_easy_strerror(result))); } @@ -1416,15 +1419,15 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo if (!SetLibcurlOption(newHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1, &result)) { throw Azure::Core::Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". Failed to set libcurl HTTP/1.1" - + ". " + std::string(curl_easy_strerror(result))); + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + + ". Failed to set libcurl HTTP/1.1" + ". " + std::string(curl_easy_strerror(result))); } auto performResult = curl_easy_perform(newHandle); if (performResult != CURLE_OK) { throw Http::TransportException( - _detail::DefaultFailedToGetNewConnectionTemplate + host + ". " + _detail::DefaultFailedToGetNewConnectionTemplate + hostDisplayName + ". " + std::string(curl_easy_strerror(performResult))); } diff --git a/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp b/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp index 720a35740..50b4d10db 100644 --- a/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp +++ b/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp @@ -26,6 +26,16 @@ using testing::ValuesIn; using namespace Azure::Core::Http::_detail; using namespace std::chrono_literals; +namespace { +inline std::string CreateConnectionKey( + std::string const& schema, + std::string const& host, + std::string const& configurationKey) +{ + return schema + "://" + host + configurationKey; +} +} // namespace + namespace Azure { namespace Core { namespace Test { /*********************** Unique Tests for Libcurl ********************************/ @@ -44,8 +54,8 @@ namespace Azure { namespace Core { namespace Test { // Use the same request for all connections. Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(AzureSdkHttpbinServer::Get())); - std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "001100"; + std::string const expectedConnectionKey(CreateConnectionKey( + AzureSdkHttpbinServer::Schema(), AzureSdkHttpbinServer::Host(), "001100")); { // Creating a new connection with default options @@ -114,7 +124,7 @@ namespace Azure { namespace Core { namespace Test { // Now test that using a different connection config won't re-use the same connection std::string const secondExpectedKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "00100200000"; + = AzureSdkHttpbinServer::Schema() + "://" + AzureSdkHttpbinServer::Host() + "00100200000"; { // Creating a new connection with options Azure::Core::Http::CurlTransportOptions options; @@ -404,8 +414,8 @@ namespace Azure { namespace Core { namespace Test { std::string const authority(AzureSdkHttpbinServer::Get()); Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); - std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "001100"; + std::string const expectedConnectionKey(CreateConnectionKey( + AzureSdkHttpbinServer::Schema(), AzureSdkHttpbinServer::Host(), "001100")); // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool @@ -440,8 +450,8 @@ namespace Azure { namespace Core { namespace Test { std::string const authority(AzureSdkHttpbinServer::WithPort()); Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); - std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "443001100"; + std::string const expectedConnectionKey(CreateConnectionKey( + AzureSdkHttpbinServer::Schema(), AzureSdkHttpbinServer::Host(), ":443001100")); // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool @@ -477,8 +487,8 @@ namespace Azure { namespace Core { namespace Test { std::string const authority(AzureSdkHttpbinServer::Get()); Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); - std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "001100"; + std::string const expectedConnectionKey(CreateConnectionKey( + AzureSdkHttpbinServer::Schema(), AzureSdkHttpbinServer::Host(), "001100")); // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool @@ -512,8 +522,8 @@ namespace Azure { namespace Core { namespace Test { std::string const authority(AzureSdkHttpbinServer::WithPort()); Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); - std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "443001100"; + std::string const expectedConnectionKey(CreateConnectionKey( + AzureSdkHttpbinServer::Schema(), AzureSdkHttpbinServer::Host(), ":443001100")); // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool