Skip to content

Commit

Permalink
support connection close header (#2672)
Browse files Browse the repository at this point in the history
  • Loading branch information
vhvb1989 authored Jul 27, 2021
1 parent c8a45ad commit 0567145
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 2 deletions.
5 changes: 4 additions & 1 deletion sdk/core/azure-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
## 1.2.0-beta.1 (Unreleased)

### Features Added
- Added `Azure::Core::IO::ProgressBodyStream` type that wraps an existing BodyStream based type stream and reports progress via callback when the stream position is updated.

- Added `Azure::Core::IO::ProgressBodyStream` type that wraps an existing BodyStream based type stream and reports progress via callback when the stream position is updated.

### Breaking Changes

### Bugs Fixed

- [2647](https://github.com/Azure/azure-sdk-for-cpp/issues/2647) Make the curl transport adapter to check the connection close header.

### Other Changes

## 1.1.0 (2021-07-02)
Expand Down
15 changes: 14 additions & 1 deletion sdk/core/azure-core/src/http/curl/curl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,20 @@ void CurlSession::ReadStatusLineAndHeadersFromRawResponse(
}

// headers are already lowerCase at this point
auto headers = this->m_response->GetHeaders();
auto const& headers = this->m_response->GetHeaders();

// Check if server has return the connection header. This header can be used to stop re-using the
// connection. The `Iot Edge Blob Storage Module` is known to return this after some time re-using
// the same http secured channel.
auto connectionHeader = headers.find("connection");
if (connectionHeader != headers.end())
{
if (connectionHeader->second == "close")
{
// Use connection shut-down so it won't be moved it back to the connection pool.
m_connection->Shutdown();
}
}

auto isContentLengthHeaderInResponse = headers.find("content-length");
if (isContentLengthHeaderInResponse != headers.end())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
namespace Azure { namespace Core { namespace Test {
class CurlConnectionPool_connectionPoolTest_Test;
class CurlConnectionPool_uniquePort_Test;
class CurlConnectionPool_connectionClose_Test;
}}} // namespace Azure::Core::Test
#endif

Expand All @@ -46,6 +47,7 @@ namespace Azure { namespace Core { namespace Http { namespace _detail {
// Give access to private to this tests class
friend class Azure::Core::Test::CurlConnectionPool_connectionPoolTest_Test;
friend class Azure::Core::Test::CurlConnectionPool_uniquePort_Test;
friend class Azure::Core::Test::CurlConnectionPool_connectionClose_Test;
#endif

public:
Expand Down
40 changes: 40 additions & 0 deletions sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,5 +554,45 @@ namespace Azure { namespace Core { namespace Test {
}
}

TEST(CurlConnectionPool, connectionClose)
{
/// When getting the header connection: close from an HTTP response, the connection should not
/// be moved back to the pool.
{
std::lock_guard<std::mutex> lock(
CurlConnectionPool::g_curlConnectionPool.ConnectionPoolMutex);
CurlConnectionPool::g_curlConnectionPool.ConnectionPoolIndex.clear();
// Make sure there are nothing in the pool
EXPECT_EQ(CurlConnectionPool::g_curlConnectionPool.ConnectionPoolIndex.size(), 0);
}

// Use the same request for all connections.
Azure::Core::Http::Request req(
Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(AzureSdkHttpbinServer::Headers()));
// Server will return this header back
req.SetHeader("connection", "close");

{
// Create a pipeline to send the request and dispose after it.
Azure::Core::Http::_internal::HttpPipeline pipeline({}, "test", "test", {}, {});
auto response = pipeline.Send(req, Azure::Core::Context::ApplicationContext);
EXPECT_PRED2(
[](Azure::Core::Http::HttpStatusCode a, Azure::Core::Http::HttpStatusCode b) {
return a == b;
},
response->GetStatusCode(),
Azure::Core::Http::HttpStatusCode::Ok);
}

// Check that after the connection is gone, it is moved back to the pool
{
std::lock_guard<std::mutex> lock(
CurlConnectionPool::g_curlConnectionPool.ConnectionPoolMutex);
EXPECT_EQ(
Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool.ConnectionPoolIndex
.size(),
0);
}
}
#endif
}}} // namespace Azure::Core::Test
5 changes: 5 additions & 0 deletions sdk/core/azure-core/test/ut/transport_adapter_base_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ namespace Azure { namespace Core { namespace Test {
return std::string(_detail::AzureSdkHttpbinServerSchema) + "://"
+ std::string(_detail::AzureSdkHttpbinServer) + "/get";
}
inline static std::string Headers()
{
return std::string(_detail::AzureSdkHttpbinServerSchema) + "://"
+ std::string(_detail::AzureSdkHttpbinServer) + "/headers";
}
inline static std::string WithPort()
{
return std::string(_detail::AzureSdkHttpbinServerSchema) + "://"
Expand Down

0 comments on commit 0567145

Please sign in to comment.