From e626133f463b6df2630be14d50df2a4b9c232bf2 Mon Sep 17 00:00:00 2001 From: Richard Peters Date: Tue, 12 Nov 2024 13:42:03 +0100 Subject: [PATCH] fix: in HttpClientApplication don't crash when detaching during StatusAvailable (#770) --- services/network/HttpClientAuthentication.cpp | 6 +++-- .../test/TestHttpClientAuthentication.cpp | 27 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/services/network/HttpClientAuthentication.cpp b/services/network/HttpClientAuthentication.cpp index bfcba448e..065ad846b 100644 --- a/services/network/HttpClientAuthentication.cpp +++ b/services/network/HttpClientAuthentication.cpp @@ -155,7 +155,8 @@ namespace services Observer().StatusAvailable(HttpStatusCode::Unauthorized); } - Observer().BodyComplete(); + if (HttpClient::IsAttached()) + Observer().BodyComplete(); } void HttpClientAuthentication::SendStreamAvailable(infra::SharedPtr&& writer) @@ -170,7 +171,8 @@ namespace services void HttpClientAuthentication::Detaching() { - HttpClient::Detach(); + if (HttpClient::IsAttached()) + HttpClient::Detach(); HttpClientObserver::Detaching(); } diff --git a/services/network/test/TestHttpClientAuthentication.cpp b/services/network/test/TestHttpClientAuthentication.cpp index 3ee68ffe2..6128d34e2 100644 --- a/services/network/test/TestHttpClientAuthentication.cpp +++ b/services/network/test/TestHttpClientAuthentication.cpp @@ -37,7 +37,8 @@ class HttpClientAuthenticationTest ~HttpClientAuthenticationTest() override { - EXPECT_CALL(*httpClientObserver, Detaching()); + if (httpClientObserver->IsAttached()) + EXPECT_CALL(*httpClientObserver, Detaching()); } void CheckHeaders(services::HttpHeaders headersToCheck, infra::BoundedConstString headerValueToAdd) @@ -261,3 +262,27 @@ TEST_F(HttpClientAuthenticationTest, unauthorized_is_retried) })); httpClient.Observer().BodyComplete(); } + +TEST_F(HttpClientAuthenticationTest, detach_during_StatusAvailable) +{ + Get(); + + httpClient.Observer().StatusAvailable(services::HttpStatusCode::Unauthorized); + + httpClient.Observer().HeaderAvailable({ "name", "value" }); + EXPECT_CALL(clientAuthentication, AuthenticationHeader()).WillOnce(testing::Return("header contents")); + EXPECT_CALL(clientAuthentication, Authenticate(services::HttpVerb::get, "target", "scheme", "value")); + httpClient.Observer().HeaderAvailable({ "WWW-Authenticate", "scheme value" }); + + testing::StrictMock reader; + EXPECT_CALL(reader, Empty()).WillOnce(testing::Return(true)); + httpClient.Observer().BodyAvailable(infra::UnOwnedSharedPtr(reader)); + + EXPECT_CALL(clientAuthentication, Retry()).WillOnce(testing::Return(false)); + EXPECT_CALL(*httpClientObserver, StatusAvailable(services::HttpStatusCode::Unauthorized)).WillOnce(testing::Invoke([this](services::HttpStatusCode) + { + EXPECT_CALL(*httpClientObserver, Detaching()); + httpClientObserver->Detach(); + })); + httpClient.Observer().BodyComplete(); +}