Program Listing for File http_socket.hpp¶
↰ Return to documentation for file (stream-client/stream/http_socket.hpp
)
#pragma once
#include "detail/static_allocator.hpp"
#include "dgram_socket.hpp"
#include "ssl_stream_socket.hpp"
#include "stream_socket.hpp"
#include <boost/beast/core/flat_buffer.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/parser.hpp>
#include <boost/beast/http/read.hpp>
#include <boost/beast/http/string_body.hpp>
#include <boost/beast/http/write.hpp>
namespace stream_client {
namespace http {
template <typename Stream>
class base_socket
{
public:
static const size_t kHeaderLimit;
static const size_t kBodyLimit;
using allocator_type = std::allocator<char>;
using next_layer_type = typename std::remove_reference<Stream>::type;
using protocol_type = typename next_layer_type::protocol_type;
using endpoint_type = typename next_layer_type::endpoint_type;
using clock_type = typename next_layer_type::clock_type;
using time_duration_type = typename next_layer_type::time_duration_type;
using time_point_type = typename next_layer_type::time_point_type;
template <class Arg1, class... ArgN,
class = typename std::enable_if<
!std::is_same<typename std::decay<Arg1>::type, base_socket<Stream>>::value>::type>
base_socket(Arg1&& arg1, ArgN&&... argn)
: stream_(std::forward<Arg1>(arg1), std::forward<ArgN>(argn)...)
, buffer_(kBodyLimit + kHeaderLimit)
{
}
base_socket(const base_socket<Stream>& other) = delete;
base_socket<Stream>& operator=(const base_socket<Stream>& other) = delete;
base_socket(base_socket<Stream>&& other) = default;
base_socket<Stream>& operator=(base_socket<Stream>&& other) = default;
virtual ~base_socket() = default;
template <typename Body, typename Fields>
boost::optional<boost::beast::http::response<Body, Fields>>
perform(const boost::beast::http::request<Body, Fields>& request, boost::system::error_code& ec,
const time_point_type& deadline);
template <typename Body, typename Fields>
inline boost::optional<boost::beast::http::response<Body, Fields>>
perform(const boost::beast::http::request<Body, Fields>& request, boost::system::error_code& ec,
const time_duration_type& timeout)
{
return perform(request, ec, clock_type::now() + timeout);
}
template <typename Body, typename Fields>
inline boost::optional<boost::beast::http::response<Body, Fields>>
perform(const boost::beast::http::request<Body, Fields>& request, boost::system::error_code& ec)
{
return perform(request, ec, stream_.io_timeout());
}
template <typename Body, typename Fields>
inline boost::beast::http::response<Body, Fields> perform(const boost::beast::http::request<Body, Fields>& request)
{
boost::system::error_code ec;
auto response = perform(request, ec);
if (ec) {
throw boost::system::system_error{ec};
}
if (!response) {
throw boost::system::system_error{boost::asio::error::operation_aborted};
}
return *response;
}
inline const next_layer_type& next_layer() const
{
return stream_;
}
inline next_layer_type& next_layer()
{
return stream_;
}
inline bool is_open() const
{
return next_layer().is_open();
}
protected:
template <typename Body, typename Fields>
void send_request(const boost::beast::http::request<Body, Fields>& request, boost::system::error_code& ec,
const time_point_type& deadline);
template <typename Parser, typename DynamicBuffer>
void recv_response(Parser& response_parser, DynamicBuffer& buffer, boost::system::error_code& ec,
const time_point_type& deadline);
template <typename Body, typename Fields>
boost::optional<boost::beast::http::response<Body, Fields>> recv_response(boost::system::error_code& ec,
const time_point_type& deadline);
private:
Stream stream_;
boost::beast::basic_flat_buffer<allocator_type> buffer_;
};
using http_client = base_socket<::stream_client::tcp_client>;
using https_client = base_socket<::stream_client::ssl::ssl_client>;
} // namespace http
} // namespace stream_client
#include "impl/http_socket.ipp"