Skip to content

Commit 548139f

Browse files
committed
CurlHttpClient.cpp: move HeadersReceivedEventHandler to WriteHeader callback
1 parent 03b3c21 commit 548139f

2 files changed

Lines changed: 39 additions & 6 deletions

File tree

src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ struct CurlWriteCallbackContext
138138
m_request(request),
139139
m_response(response),
140140
m_rateLimiter(rateLimiter),
141-
m_numBytesResponseReceived(0)
141+
m_numBytesResponseReceived(0),
142+
m_headersReceivedEventFired(false)
142143
{}
143144

144145
const CurlHttpClient* m_client;
@@ -147,6 +148,7 @@ struct CurlWriteCallbackContext
147148
HttpResponse* m_response;
148149
Aws::Utils::RateLimits::RateLimiterInterface* m_rateLimiter;
149150
int64_t m_numBytesResponseReceived;
151+
bool m_headersReceivedEventFired;
150152
};
151153

152154
static const char* CURL_HTTP_CLIENT_TAG = "CurlHttpClient";
@@ -194,11 +196,6 @@ static size_t WriteData(char* ptr, size_t size, size_t nmemb, void* userdata)
194196
}
195197

196198
HttpResponse* response = context->m_response;
197-
auto& headersHandler = context->m_request->GetHeadersReceivedEventHandler();
198-
if (context->m_numBytesResponseReceived == 0 && headersHandler)
199-
{
200-
headersHandler(context->m_request, context->m_response);
201-
}
202199

203200
size_t sizeToWrite = size * nmemb;
204201
if (context->m_rateLimiter)
@@ -284,6 +281,16 @@ static size_t WriteHeader(char* ptr, size_t size, size_t nmemb, void* userdata)
284281
curl_easy_getinfo(context->m_curlHandle, CURLINFO_RESPONSE_CODE, &responseCode);
285282
response->SetResponseCode(static_cast<HttpResponseCode>(responseCode));
286283
AWS_LOGSTREAM_DEBUG(CURL_HTTP_CLIENT_TAG, "Returned http response code " << responseCode);
284+
285+
if (!context->m_headersReceivedEventFired)
286+
{
287+
auto& headersHandler = context->m_request->GetHeadersReceivedEventHandler();
288+
if (headersHandler)
289+
{
290+
headersHandler(context->m_request, context->m_response);
291+
}
292+
context->m_headersReceivedEventFired = true;
293+
}
287294
}
288295

289296
return size * nmemb;

tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,6 +2690,32 @@ namespace
26902690
EXPECT_FALSE(outcome.IsSuccess());
26912691
}
26922692

2693+
TEST_F(BucketAndObjectOperationTest, TestHeadersReceivedEventHandlerFiresOnEmptyBodyResponse) {
2694+
const String fullBucketName = CalculateBucketName(BASE_PUT_OBJECTS_BUCKET_NAME.c_str());
2695+
SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName);
2696+
2697+
// PutObject returns 200 with headers but an empty body
2698+
Aws::S3::Model::PutObjectRequest request;
2699+
request.SetBucket(fullBucketName);
2700+
request.SetKey("headers-received-handler-test");
2701+
2702+
auto body = Aws::MakeShared<Aws::StringStream>(ALLOCATION_TAG, "test content");
2703+
request.SetBody(body);
2704+
2705+
std::atomic<bool> handlerFired{false};
2706+
Aws::Http::HttpResponseCode capturedCode{Aws::Http::HttpResponseCode::REQUEST_NOT_MADE};
2707+
request.SetHeadersReceivedEventHandler(
2708+
[&handlerFired, &capturedCode](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse* response) {
2709+
handlerFired = true;
2710+
capturedCode = response->GetResponseCode();
2711+
});
2712+
2713+
auto outcome = Client->PutObject(request);
2714+
AWS_EXPECT_SUCCESS(outcome);
2715+
EXPECT_TRUE(handlerFired.load()) << "HeadersReceivedEventHandler must fire even when response body is empty";
2716+
EXPECT_EQ(Aws::Http::HttpResponseCode::OK, capturedCode);
2717+
}
2718+
26932719
TEST_F(BucketAndObjectOperationTest, ShouldSkipResponseValidationOnCompositeChecksums) {
26942720
const auto fullBucketName = CalculateBucketName(BASE_PUT_MULTIPART_COMPOSITE_CHECKSUM_BUCKET_NAME.c_str());
26952721
m_bucketsToDelete.insert(fullBucketName);

0 commit comments

Comments
 (0)