Я играю с частью Beast в Boost и пытаюсь создать простой http-клиент, который можно использовать для / GET содержимого из веб-ресурса (простые службы HTML или REST).).
Я использовал пример, который можно найти в github repo beast для http-клиента синхронизации, и переместил его в простой класс с именем http_client :
Заголовок:
#ifndef HTTP_CLIENT_HPP
#define HTTP_CLIENT_HPP
#include <string>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
namespace playground
{
namespace net
{
namespace beast = boost::beast;
class http_client
{
public:
beast::http::response<beast::http::string_body>
get(std::string base_url,
std::string path,
std::string port = "80",
unsigned short http_version = 11);
};
}
}
#endif
Реализация:
#include <iostream>
#include <string>
#include <cstdlib>
#include <stdexcept>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include "http_client.hpp"
namespace playground
{
namespace net
{
namespace beast = boost::beast;
namespace asio = boost::asio;
beast::http::response<beast::http::string_body>
http_client::get(std::string base_url,
std::string path,
std::string port,
unsigned short http_version)
{
std::cout << "HttpClient::getAsync()" << std::endl;
beast::http::response <boost::beast::http::string_body> httpResponse;
asio::io_context ioContext;
asio::ip::tcp::resolver tcpResolver
{ ioContext };
asio::ip::tcp::socket tcpSocket
{ ioContext };
beast::http::request <beast::http::string_body> httpRequest(beast::http::verb::get,
path,
http_version);
beast::error_code connectionError;
beast::error_code readError;
beast::flat_buffer responseBuffer;
try
{
auto const ipAddresses = tcpResolver.resolve(base_url, port);
asio::connect(tcpSocket,
ipAddresses.begin(),
ipAddresses.end());
if (tcpSocket.is_open())
{
httpRequest.set(beast::http::field::host, base_url);
httpRequest.set(beast::http::field::user_agent,
"http_client");
httpRequest.set(beast::http::field::accept, "text/xml");
beast::http::write(tcpSocket, httpRequest);
beast::http::read(tcpSocket,
responseBuffer,
httpResponse,
readError);
if (readError != beast::http::error::end_of_stream)
{
throw std::runtime_error(readError.message());
}
tcpSocket.shutdown(asio::ip::tcp::socket::shutdown_both,
connectionError);
if (connectionError
&& connectionError != beast::errc::not_connected)
{
throw beast::system_error(connectionError);
}
}
else
{
throw std::runtime_error("Unable to open connection!");
}
}
catch (std::exception const& ex)
{
throw;
}
return httpResponse;
}
}
}
Проблема в том, что данный string_body пуст, хотя http-код состояния равен 200.
Примерзвонок:
playground::net::http_client client;
std::string url("www.google.de");
auto response = client.get(url, "/", "443");
std::cout << "Response: " << response << std::endl;
std::cout << "Response body: " << response.body() << std::endl;
Чего-то не хватает в звонке?