Skip to content

Commit b2bf6a8

Browse files
committed
- Renamed HttpClientInterface to HttpClientBase
- Added validation for Json parsing of connection config file. - Cleaned up error messages and exceptions.
1 parent 03d9f51 commit b2bf6a8

17 files changed

+192
-123
lines changed

CMakeLists.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ target_link_libraries(dbps_server_lib PUBLIC OpenSSL::SSL OpenSSL::Crypto)
160160
# Client components library (depends on httplib, nlohmann/json, and cppcodec)
161161
add_library(dbps_client_lib STATIC
162162
src/client/dbps_api_client.cpp
163-
src/client/http_client_interface.cpp
163+
src/client/http_client_base.cpp
164164
src/client/httplib_client.cpp
165165
src/client/httplib_pool_registry.cpp
166166
src/client/httplib_pooled_client.cpp
@@ -366,8 +366,8 @@ if(BUILD_TESTS)
366366
)
367367

368368
# Http client interface tests
369-
add_executable(http_client_interface_test src/client/http_client_interface_test.cpp)
370-
target_link_libraries(http_client_interface_test
369+
add_executable(http_client_base_test src/client/http_client_base_test.cpp)
370+
target_link_libraries(http_client_base_test
371371
dbps_client_lib
372372
dbps_common_lib
373373
gtest_main
@@ -402,7 +402,7 @@ if(BUILD_SHARED_LIBS)
402402
src/common/dbps_remote_shared_lib_wrapper.cpp
403403
src/common/dbpa_remote.cpp
404404
src/client/dbps_api_client.cpp
405-
src/client/http_client_interface.cpp
405+
src/client/http_client_base.cpp
406406
src/client/httplib_client.cpp
407407
src/common/json_request.cpp
408408
)
@@ -506,7 +506,7 @@ if(BUILD_TESTS)
506506
dbpa_local_test
507507
httplib_pool_registry_test
508508
httplib_pooled_client_test
509-
http_client_interface_test
509+
http_client_base_test
510510
COMMENT "Building all tests"
511511
)
512512

@@ -528,7 +528,7 @@ if(BUILD_TESTS)
528528
gtest_discover_tests(dbpa_local_test)
529529
gtest_discover_tests(httplib_pool_registry_test)
530530
gtest_discover_tests(httplib_pooled_client_test)
531-
gtest_discover_tests(http_client_interface_test)
531+
gtest_discover_tests(http_client_base_test)
532532
endif()
533533

534534
# All target (everything)

src/client/dbps_api_client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ void DecryptApiResponse::SetJsonRequest(const DecryptJsonRequest& request) { jso
159159
bool DecryptApiResponse::HasJsonRequest() const { return json_request_.has_value(); }
160160
const JsonRequest& DecryptApiResponse::GetJsonRequest() const { return json_request_.value(); }
161161

162-
DBPSApiClient::DBPSApiClient(std::shared_ptr<HttpClientInterface> http_client)
162+
DBPSApiClient::DBPSApiClient(std::shared_ptr<HttpClientBase> http_client)
163163
: http_client_(std::move(http_client)) {
164164
}
165165

src/client/dbps_api_client.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "../common/enum_utils.h"
2727
#include "../common/json_request.h"
2828
#include "tcb/span.hpp"
29-
#include "http_client_interface.h"
29+
#include "http_client_base.h"
3030

3131
using namespace dbps::external;
3232
using namespace dbps::enum_utils;
@@ -143,7 +143,7 @@ class DBPSApiClient {
143143
* The HTTP client is expected to be thread-safe.
144144
* @param http_client Custom HTTP client implementation
145145
*/
146-
explicit DBPSApiClient(std::shared_ptr<HttpClientInterface> http_client);
146+
explicit DBPSApiClient(std::shared_ptr<HttpClientBase> http_client);
147147

148148
/**
149149
* Destructor
@@ -223,5 +223,5 @@ class DBPSApiClient {
223223
);
224224

225225
private:
226-
const std::shared_ptr<HttpClientInterface> http_client_;
226+
const std::shared_ptr<HttpClientBase> http_client_;
227227
};

src/client/dbps_api_client_test.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <algorithm>
2323
#include "tcb/span.hpp"
2424
#include "dbps_api_client.h"
25-
#include "http_client_interface.h"
25+
#include "http_client_base.h"
2626
#include "../common/enums.h"
2727
#include <nlohmann/json.hpp>
2828
#include <gtest/gtest.h>
@@ -56,10 +56,10 @@ bool CompareJsonStrings(const std::string& json1, const std::string& json2, cons
5656
}
5757

5858
// Mock HTTP client for testing
59-
class MockHttpClient : public HttpClientInterface {
59+
class MockHttpClient : public HttpClientBase {
6060
public:
6161
MockHttpClient()
62-
: HttpClientInterface(
62+
: HttpClientBase(
6363
"mock://",
6464
ClientCredentials{{"client_id", "test_client_AAAA"}, {"api_key", "test_key_AAAA"}}) {
6565
}
@@ -310,7 +310,7 @@ TEST(DBPSApiClient, EncryptWithValidData) {
310310
})";
311311

312312
mock_client->SetMockPostResponse("/encrypt", expected_request,
313-
HttpClientInterface::HttpResponse(200, mock_response));
313+
HttpClientBase::HttpResponse(200, mock_response));
314314

315315
// Create DBPSApiClient with mock client
316316
DBPSApiClient client(std::move(mock_client));
@@ -402,7 +402,7 @@ TEST(DBPSApiClient, DecryptWithValidData) {
402402
})";
403403

404404
mock_client->SetMockPostResponse("/decrypt", expected_request,
405-
HttpClientInterface::HttpResponse(200, mock_response));
405+
HttpClientBase::HttpResponse(200, mock_response));
406406

407407
// Create DBPSApiClient with mock client
408408
DBPSApiClient client(std::move(mock_client));
@@ -545,7 +545,7 @@ TEST(DBPSApiClient, EncryptWithInvalidJsonResponse) {
545545
})";
546546

547547
mock_client->SetMockPostResponse("/encrypt", expected_request,
548-
HttpClientInterface::HttpResponse(200, mock_response));
548+
HttpClientBase::HttpResponse(200, mock_response));
549549

550550
// Create DBPSApiClient with mock client
551551
DBPSApiClient client(std::move(mock_client));
@@ -611,7 +611,7 @@ TEST(DBPSApiClient, DecryptWithInvalidJsonResponse) {
611611
})";
612612

613613
mock_client->SetMockPostResponse("/decrypt", expected_request,
614-
HttpClientInterface::HttpResponse(200, mock_response));
614+
HttpClientBase::HttpResponse(200, mock_response));
615615

616616
// Create DBPSApiClient with mock client
617617
DBPSApiClient client(std::move(mock_client));
@@ -688,7 +688,7 @@ TEST(DBPSApiClient, EncryptWithEncodingAttributes) {
688688
})";
689689

690690
mock_client->SetMockPostResponse("/encrypt", expected_request,
691-
HttpClientInterface::HttpResponse(200, mock_response));
691+
HttpClientBase::HttpResponse(200, mock_response));
692692

693693
// Create DBPSApiClient with mock client
694694
DBPSApiClient client(std::move(mock_client));

src/client/http_client_base.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,28 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
#include "http_client_interface.h"
18+
#include "http_client_base.h"
1919

2020
#include <chrono>
2121

2222
#include "json_request.h"
2323

24-
HttpClientInterface::HeaderList HttpClientInterface::DefaultJsonGetHeaders() {
24+
HttpClientBase::HeaderList HttpClientBase::DefaultJsonGetHeaders() {
2525
HeaderList headers;
2626
headers.insert({"Accept", kJsonContentType});
2727
headers.insert({"User-Agent", kDefaultUserAgent});
2828
return headers;
2929
}
3030

31-
HttpClientInterface::HeaderList HttpClientInterface::DefaultJsonPostHeaders() {
31+
HttpClientBase::HeaderList HttpClientBase::DefaultJsonPostHeaders() {
3232
HeaderList headers;
3333
headers.insert({"Content-Type", kJsonContentType});
3434
headers.insert({"Accept", kJsonContentType});
3535
headers.insert({"User-Agent", kDefaultUserAgent});
3636
return headers;
3737
}
3838

39-
HttpClientInterface::HttpResponse HttpClientInterface::Get(const std::string& endpoint, bool auth_required) {
39+
HttpClientBase::HttpResponse HttpClientBase::Get(const std::string& endpoint, bool auth_required) {
4040
const auto attempt = [&]() -> HttpResponse {
4141
auto headers = DefaultJsonGetHeaders();
4242
if (auth_required) {
@@ -56,7 +56,7 @@ HttpClientInterface::HttpResponse HttpClientInterface::Get(const std::string& en
5656
return result;
5757
}
5858

59-
HttpClientInterface::HttpResponse HttpClientInterface::Post(const std::string& endpoint,
59+
HttpClientBase::HttpResponse HttpClientBase::Post(const std::string& endpoint,
6060
const std::string& json_body,
6161
bool auth_required) {
6262
const auto attempt = [&]() -> HttpResponse {
@@ -78,7 +78,7 @@ HttpClientInterface::HttpResponse HttpClientInterface::Post(const std::string& e
7878
return result;
7979
}
8080

81-
std::string HttpClientInterface::AddAuthorizationHeader(HeaderList& headers) {
81+
std::string HttpClientBase::AddAuthorizationHeader(HeaderList& headers) {
8282
std::string token_or_error;
8383
auto token_opt = EnsureValidToken(token_or_error);
8484
if (!token_opt.has_value()) {
@@ -95,7 +95,7 @@ std::string HttpClientInterface::AddAuthorizationHeader(HeaderList& headers) {
9595
return "";
9696
}
9797

98-
std::optional<HttpClientInterface::CachedToken> HttpClientInterface::EnsureValidToken(std::string& error) {
98+
std::optional<HttpClientBase::CachedToken> HttpClientBase::EnsureValidToken(std::string& error) {
9999

100100
const auto now_epoch_seconds = []() -> std::int64_t {
101101
const auto now = std::chrono::system_clock::now();
@@ -140,7 +140,7 @@ std::optional<HttpClientInterface::CachedToken> HttpClientInterface::EnsureValid
140140
return fetched;
141141
}
142142

143-
std::optional<HttpClientInterface::CachedToken> HttpClientInterface::FetchToken(std::string& error) {
143+
std::optional<HttpClientBase::CachedToken> HttpClientBase::FetchToken(std::string& error) {
144144
error.clear();
145145
TokenRequest token_req;
146146
token_req.credential_values_ = credentials_;
@@ -169,7 +169,7 @@ std::optional<HttpClientInterface::CachedToken> HttpClientInterface::FetchToken(
169169
return result;
170170
}
171171

172-
void HttpClientInterface::InvalidateCachedToken() {
172+
void HttpClientBase::InvalidateCachedToken() {
173173
std::lock_guard<std::mutex> lock(token_mutex_);
174174
cached_token_ = std::nullopt;
175175
}

src/client/http_client_base.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
* Thread Safety: Implementations must be thread-safe for concurrent calls.
3232
* Multiple threads may call Get() and Post() methods simultaneously on the same instance.
3333
*/
34-
class HttpClientInterface {
34+
class HttpClientBase {
3535
public:
36-
virtual ~HttpClientInterface() = default;
36+
virtual ~HttpClientBase() = default;
3737

3838
using ClientCredentials = std::map<std::string, std::string>;
3939
using HeaderList = httplib::Headers;
@@ -61,7 +61,7 @@ class HttpClientInterface {
6161
HttpResponse Post(const std::string& endpoint, const std::string& json_body, bool auth_required = true);
6262

6363
protected:
64-
explicit HttpClientInterface(std::string base_url,
64+
explicit HttpClientBase(std::string base_url,
6565
ClientCredentials credentials = {})
6666
: base_url_(std::move(base_url)),
6767
credentials_(std::move(credentials)) {

src/client/http_client_base_test.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@
2121
#include <string>
2222
#include <vector>
2323

24-
#include "http_client_interface.h"
24+
#include "http_client_base.h"
2525

26-
class FakeHttpClient final : public HttpClientInterface {
26+
class FakeHttpClient final : public HttpClientBase {
2727
public:
2828
explicit FakeHttpClient(ClientCredentials credentials)
29-
: HttpClientInterface("mock://", std::move(credentials)) {
29+
: HttpClientBase("mock://", std::move(credentials)) {
3030
}
3131

3232
void SetTokenResponse(std::string token, std::string token_type, std::int64_t expires_at) {
@@ -104,15 +104,15 @@ class FakeHttpClient final : public HttpClientInterface {
104104
std::int64_t expires_at_ = 4102444800; // 2100-01-01T00:00:00Z
105105
};
106106

107-
TEST(HttpClientInterfaceTest, AuthRequiredDefaultFetchesTokenAndAddsAuthorizationHeader) {
107+
TEST(HttpClientBaseTest, AuthRequiredDefaultFetchesTokenAndAddsAuthorizationHeader) {
108108
FakeHttpClient client({{"client_id", "clientA"}, {"api_key", "keyA"}});
109109
client.SetTokenResponse("abc", "Bearer", 4102444800);
110110

111111
auto r1 = client.Get("/statusz");
112112
ASSERT_TRUE(r1.error_message.empty());
113113
ASSERT_EQ(r1.status_code, 200);
114114

115-
auto auth_it = client.last_get_headers.find(HttpClientInterface::kAuthorizationHeader);
115+
auto auth_it = client.last_get_headers.find(HttpClientBase::kAuthorizationHeader);
116116
ASSERT_NE(auth_it, client.last_get_headers.end());
117117
ASSERT_EQ(auth_it->second, "Bearer abc");
118118

@@ -124,31 +124,31 @@ TEST(HttpClientInterfaceTest, AuthRequiredDefaultFetchesTokenAndAddsAuthorizatio
124124
ASSERT_EQ(client.get_calls.load(), 2);
125125
}
126126

127-
TEST(HttpClientInterfaceTest, AuthRequiredFalseDoesNotFetchTokenOrSendAuthorizationHeader) {
127+
TEST(HttpClientBaseTest, AuthRequiredFalseDoesNotFetchTokenOrSendAuthorizationHeader) {
128128
FakeHttpClient client({{"client_id", "clientA"}, {"api_key", "keyA"}});
129129

130130
auto r = client.Get("/healthz", false);
131131
ASSERT_TRUE(r.error_message.empty());
132132
ASSERT_EQ(r.status_code, 200);
133133
ASSERT_EQ(client.token_calls.load(), 0);
134134
ASSERT_EQ(client.get_calls.load(), 1);
135-
ASSERT_EQ(client.last_get_headers.find(HttpClientInterface::kAuthorizationHeader),
135+
ASSERT_EQ(client.last_get_headers.find(HttpClientBase::kAuthorizationHeader),
136136
client.last_get_headers.end());
137137
}
138138

139-
TEST(HttpClientInterfaceTest, UsesTokenTypeFromTokenResponse) {
139+
TEST(HttpClientBaseTest, UsesTokenTypeFromTokenResponse) {
140140
FakeHttpClient client({{"client_id", "clientA"}, {"api_key", "keyA"}});
141141
client.SetTokenResponse("xyz", "JWT", 4102444800);
142142

143143
auto r = client.Get("/statusz");
144144
ASSERT_TRUE(r.error_message.empty());
145145

146-
auto auth_it = client.last_get_headers.find(HttpClientInterface::kAuthorizationHeader);
146+
auto auth_it = client.last_get_headers.find(HttpClientBase::kAuthorizationHeader);
147147
ASSERT_NE(auth_it, client.last_get_headers.end());
148148
ASSERT_EQ(auth_it->second, "JWT xyz");
149149
}
150150

151-
TEST(HttpClientInterfaceTest, RetryOnceOn401FetchesNewTokenAndRetries) {
151+
TEST(HttpClientBaseTest, RetryOnceOn401FetchesNewTokenAndRetries) {
152152
FakeHttpClient client({{"client_id", "clientA"}, {"api_key", "keyA"}});
153153
client.SetTokenResponses({
154154
{"t1", "Bearer", 4102444800},
@@ -164,8 +164,8 @@ TEST(HttpClientInterfaceTest, RetryOnceOn401FetchesNewTokenAndRetries) {
164164
ASSERT_EQ(client.get_calls.load(), 2);
165165

166166
ASSERT_GE(client.get_headers_history.size(), 2u);
167-
auto auth1 = client.get_headers_history[0].find(HttpClientInterface::kAuthorizationHeader);
168-
auto auth2 = client.get_headers_history[1].find(HttpClientInterface::kAuthorizationHeader);
167+
auto auth1 = client.get_headers_history[0].find(HttpClientBase::kAuthorizationHeader);
168+
auto auth2 = client.get_headers_history[1].find(HttpClientBase::kAuthorizationHeader);
169169
ASSERT_NE(auth1, client.get_headers_history[0].end());
170170
ASSERT_NE(auth2, client.get_headers_history[1].end());
171171
ASSERT_EQ(auth1->second, "Bearer t1");

src/client/httplib_client.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
#include "httplib_client.h"
1919

2020
HttplibClient::HttplibClient(const std::string& base_url, ClientCredentials credentials)
21-
: HttpClientInterface(base_url, std::move(credentials)) {
21+
: HttpClientBase(base_url, std::move(credentials)) {
2222
}
2323

24-
HttpClientInterface::HttpResponse HttplibClient::DoGet(const std::string& endpoint, const HeaderList& headers) {
24+
HttpClientBase::HttpResponse HttplibClient::DoGet(const std::string& endpoint, const HeaderList& headers) {
2525
try {
2626
httplib::Client client(base_url_);
2727

@@ -42,15 +42,15 @@ HttpClientInterface::HttpResponse HttplibClient::DoGet(const std::string& endpoi
4242
}
4343
}
4444

45-
HttpClientInterface::HttpResponse HttplibClient::DoPost(const std::string& endpoint, const std::string& json_body, const HeaderList& headers) {
45+
HttpClientBase::HttpResponse HttplibClient::DoPost(const std::string& endpoint, const std::string& json_body, const HeaderList& headers) {
4646
try {
4747
httplib::Client client(base_url_);
4848

4949
client.set_connection_timeout(10);
5050
client.set_read_timeout(30);
5151

5252
// Make the POST request
53-
auto result = client.Post(endpoint, headers, json_body, HttpClientInterface::kJsonContentType);
53+
auto result = client.Post(endpoint, headers, json_body, HttpClientBase::kJsonContentType);
5454

5555
if (!result) {
5656
return HttpResponse(0, "", "HTTP POST request failed: no response received");

src/client/httplib_client.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@
1717

1818
#pragma once
1919

20-
#include "http_client_interface.h"
20+
#include "http_client_base.h"
2121
#include <httplib.h>
2222

23-
class HttplibClient : public HttpClientInterface {
23+
class HttplibClient : public HttpClientBase {
2424
public:
2525
/**
2626
* Constructs an HTTP client for a given base URL.
2727
*
2828
* @param base_url The base URL (e.g., "http://127.0.0.1:18080")
29-
* @param credentials Authentication key/value map used by HttpClientInterface to request JWTs from /token
29+
* @param credentials Authentication key/value map used by HttpClientBase to request JWTs from /token
3030
*/
3131
explicit HttplibClient(
3232
const std::string& base_url,
@@ -37,7 +37,7 @@ class HttplibClient : public HttpClientInterface {
3737
* Transport implementation for an HTTP GET to the specified endpoint.
3838
*
3939
* @param endpoint The endpoint path to request (e.g., "/healthz")
40-
* @param headers Fully prepared headers from HttpClientInterface (may include Authorization)
40+
* @param headers Fully prepared headers from HttpClientBase (may include Authorization)
4141
* @return HttpResponse containing status code, response body, and any error message
4242
*
4343
* @note Connections are not reused - a new connection is established for each request
@@ -50,7 +50,7 @@ class HttplibClient : public HttpClientInterface {
5050
*
5151
* @param endpoint The endpoint path to request (e.g., "/encrypt")
5252
* @param json_body The JSON payload to send in the request body
53-
* @param headers Fully prepared headers from HttpClientInterface (may include Authorization)
53+
* @param headers Fully prepared headers from HttpClientBase (may include Authorization)
5454
* @return HttpResponse containing status code, response body, and any error message
5555
*
5656
* @note Connections are not reused - a new connection is established for each request

0 commit comments

Comments
 (0)