Skip to content

Commit

Permalink
fix: create a function to avoid duplicate code in the ReadToFile meth…
Browse files Browse the repository at this point in the history
…ods of the HttpSocket and HttpsSocket classes.
  • Loading branch information
Nicogp committed Oct 16, 2024
1 parent 9de024c commit 4f1cc31
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 105 deletions.
2 changes: 1 addition & 1 deletion src/agent/communicator/include/http_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace http_client
const bool useHttps) override;

boost::beast::http::response<boost::beast::http::dynamic_body>
PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& output_file) override;
PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& dstFilePath) override;

private:
std::shared_ptr<IHttpResolverFactory> m_resolverFactory;
Expand Down
2 changes: 1 addition & 1 deletion src/agent/communicator/include/ihttp_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,6 @@ namespace http_client
const bool useHttps) = 0;

virtual boost::beast::http::response<boost::beast::http::dynamic_body>
PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& output_file) = 0;
PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& dstFilePath) = 0;
};
} // namespace http_client
2 changes: 1 addition & 1 deletion src/agent/communicator/include/ihttp_socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace http_client
virtual void Read(boost::beast::http::response<boost::beast::http::dynamic_body>& res) = 0;

virtual void ReadToFile(boost::beast::http::response_parser<boost::beast::http::dynamic_body>& res,
const std::string& output_file) = 0;
const std::string& dstFilePath) = 0;

virtual boost::asio::awaitable<void>
AsyncRead(boost::beast::http::response<boost::beast::http::dynamic_body>& res,
Expand Down
4 changes: 2 additions & 2 deletions src/agent/communicator/src/http_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ namespace http_client
}

boost::beast::http::response<boost::beast::http::dynamic_body>
HttpClient::PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& output_file)
HttpClient::PerformHttpRequestDownload(const HttpRequestParams& params, const std::string& dstFilePath)
{
boost::beast::http::response_parser<boost::beast::http::dynamic_body> res_parser;

Expand All @@ -264,7 +264,7 @@ namespace http_client

const auto req = CreateHttpRequest(params);
socket->Write(req);
socket->ReadToFile(res_parser, output_file);
socket->ReadToFile(res_parser, dstFilePath);

LogDebug("Response code: {}.", res_parser.get().result_int());
}
Expand Down
62 changes: 62 additions & 0 deletions src/agent/communicator/src/http_client_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <ihttp_socket.hpp>

#include <boost/asio.hpp>
#include <boost/beast.hpp>

#include <fstream>
#include <string>

namespace http_client_utils
{
template<typename SocketType>
void ReadToFile(SocketType& socket,
boost::beast::http::response_parser<boost::beast::http::dynamic_body>& res,
const std::string& dstFilePath)
{
res.body_limit(std::numeric_limits<std::uint64_t>::max());
boost::beast::flat_buffer buffer;
boost::system::error_code error;

boost::beast::http::read_header(socket, buffer, res, error);

if (error && error != boost::beast::http::error::need_buffer)
{
throw boost::system::system_error(error);
}

unsigned int statusCode = res.get().result_int();
if (statusCode != 200)
{
return;
}

std::ofstream file(dstFilePath, std::ios::binary);
if (!file)
{
throw std::runtime_error("The file could not be opened for writing: " + dstFilePath);
}

while (!res.is_done())
{
boost::beast::http::read(socket, buffer, res, error);

if (error && error != boost::beast::http::error::need_buffer && error != boost::asio::error::eof)
{
file.close();
throw boost::system::system_error(error);
}

auto bodyData = res.get().body().data();

for (auto const& bufferSeq : bodyData)
{
std::streamsize chunkSize = static_cast<std::streamsize>(bufferSeq.size());
file.write(static_cast<const char*>(bufferSeq.data()), chunkSize);
}

res.get().body().consume(res.get().body().size());
}

file.close();
}
} // namespace http_client_utils
49 changes: 3 additions & 46 deletions src/agent/communicator/src/http_socket.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "http_client_utils.hpp"
#include <ihttp_socket.hpp>

#include <boost/asio.hpp>
Expand Down Expand Up @@ -46,53 +47,9 @@ namespace http_client
}

void ReadToFile(boost::beast::http::response_parser<boost::beast::http::dynamic_body>& res,
const std::string& output_file) override
const std::string& dstFilePath) override
{
res.body_limit(std::numeric_limits<std::uint64_t>::max());
boost::beast::flat_buffer buffer;
boost::system::error_code error;

boost::beast::http::read_header(m_socket, buffer, res, error);

if (error && error != boost::beast::http::error::need_buffer)
{
throw boost::system::system_error(error);
}

unsigned int status_code = res.get().result_int();
if (status_code != 200)
{
return;
}

std::ofstream file(output_file, std::ios::binary);
if (!file)
{
throw std::runtime_error("The file could not be opened for writing: " + output_file);
}

while (!res.is_done())
{
boost::beast::http::read(m_socket, buffer, res, error);

if (error && error != boost::beast::http::error::need_buffer && error != boost::asio::error::eof)
{
file.close();
throw boost::system::system_error(error);
}

auto body_data = res.get().body().data();

for (auto const& buffer_seq : body_data)
{
std::streamsize chunk_size = static_cast<std::streamsize>(buffer_seq.size());
file.write(static_cast<const char*>(buffer_seq.data()), chunk_size);
}

res.get().body().consume(res.get().body().size());
}

file.close();
http_client_utils::ReadToFile(m_socket, res, dstFilePath);
}

boost::asio::awaitable<void> AsyncRead(boost::beast::http::response<boost::beast::http::dynamic_body>& res,
Expand Down
48 changes: 2 additions & 46 deletions src/agent/communicator/src/https_socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,53 +52,9 @@ namespace http_client
}

void ReadToFile(boost::beast::http::response_parser<boost::beast::http::dynamic_body>& res,
const std::string& output_file) override
const std::string& dstFilePath) override
{
res.body_limit(std::numeric_limits<std::uint64_t>::max());
boost::beast::flat_buffer buffer;
boost::system::error_code error;

boost::beast::http::read_header(m_ssl_socket, buffer, res, error);

if (error && error != boost::beast::http::error::need_buffer)
{
throw boost::system::system_error(error);
}

unsigned int status_code = res.get().result_int();
if (status_code != 200)
{
return;
}

std::ofstream file(output_file, std::ios::binary);
if (!file)
{
throw std::runtime_error("The file could not be opened for writing: " + output_file);
}

while (!res.is_done())
{
boost::beast::http::read(m_ssl_socket, buffer, res, error);

if (error && error != boost::beast::http::error::need_buffer && error != boost::asio::error::eof)
{
file.close();
throw boost::system::system_error(error);
}

auto body_data = res.get().body().data();

for (auto const& buffer_seq : body_data)
{
std::streamsize chunk_size = static_cast<std::streamsize>(buffer_seq.size());
file.write(static_cast<const char*>(buffer_seq.data()), chunk_size);
}

res.get().body().consume(res.get().body().size());
}

file.close();
http_client_utils::ReadToFile(m_ssl_socket, res, dstFilePath);
}

boost::asio::awaitable<void> AsyncRead(boost::beast::http::response<boost::beast::http::dynamic_body>& res,
Expand Down
10 changes: 5 additions & 5 deletions src/agent/communicator/tests/http_client_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,12 +490,12 @@ TEST_F(HttpClientTest, PerformHttpRequestDownload_Success)
EXPECT_CALL(*mockSocket, Connect(_)).Times(1);
EXPECT_CALL(*mockSocket, Write(_)).Times(1);
EXPECT_CALL(*mockSocket, ReadToFile(_, _))
.WillOnce([](auto& res, [[maybe_unused]] auto& output_file)
.WillOnce([](auto& res, [[maybe_unused]] auto& dstFilePath)
{ res.get().result(boost::beast::http::status::ok); });

const http_client::HttpRequestParams params(boost::beast::http::verb::get, "localhost", "80", "/", true);
const std::string output_file = "output_file";
const auto response = client->PerformHttpRequestDownload(params, output_file);
const std::string dstFilePath = "dstFilePath";
const auto response = client->PerformHttpRequestDownload(params, dstFilePath);

EXPECT_EQ(response.result(), boost::beast::http::status::ok);
}
Expand All @@ -507,8 +507,8 @@ TEST_F(HttpClientTest, PerformHttpRequestDownload_ExceptionThrown)
EXPECT_CALL(*mockResolver, Resolve(_, _)).WillOnce(Throw(std::runtime_error("Simulated resolution failure")));

const http_client::HttpRequestParams params(boost::beast::http::verb::get, "localhost", "80", "/", true);
const std::string output_file = "output_file";
const auto response = client->PerformHttpRequestDownload(params, output_file);
const std::string dstFilePath = "dstFilePath";
const auto response = client->PerformHttpRequestDownload(params, dstFilePath);

EXPECT_EQ(response.result(), boost::beast::http::status::internal_server_error);
EXPECT_TRUE(boost::beast::buffers_to_string(response.body().data()).find("Simulated resolution failure") !=
Expand Down
2 changes: 1 addition & 1 deletion src/agent/communicator/tests/mocks/mock_http_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ class MockHttpClient : public http_client::IHttpClient

MOCK_METHOD(boost::beast::http::response<boost::beast::http::dynamic_body>,
PerformHttpRequestDownload,
(const http_client::HttpRequestParams& params, const std::string& output_file),
(const http_client::HttpRequestParams& params, const std::string& dstFilePath),
(override));
};
2 changes: 1 addition & 1 deletion src/agent/communicator/tests/mocks/mock_http_socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class MockHttpSocket : public http_client::IHttpSocket
MOCK_METHOD(void,
ReadToFile,
(boost::beast::http::response_parser<boost::beast::http::dynamic_body> & res,
const std::string& output_file),
const std::string& dstFilePath),
(override));

MOCK_METHOD(boost::asio::awaitable<void>,
Expand Down
2 changes: 1 addition & 1 deletion src/agent/tests/register_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class MockHttpClient : public http_client::IHttpClient

MOCK_METHOD(boost::beast::http::response<boost::beast::http::dynamic_body>,
PerformHttpRequestDownload,
(const http_client::HttpRequestParams& params, const std::string& output_file),
(const http_client::HttpRequestParams& params, const std::string& dstFilePath),
(override));
};

Expand Down

0 comments on commit 4f1cc31

Please sign in to comment.