Skip to content

Instantly share code, notes, and snippets.

@microcai
Last active July 2, 2019 05:51
Show Gist options
  • Save microcai/08b813e588a1eb1c966fd555d3f22eb3 to your computer and use it in GitHub Desktop.
Save microcai/08b813e588a1eb1c966fd555d3f22eb3 to your computer and use it in GitHub Desktop.
std::string easyhttp::sync::post(std::string post_url, std::string post_content, std::string content_type)
{
try
{
auto url = parse_url(post_url);
boost::asio::io_context io;
boost::asio::ssl::context ssl_ctx(boost::asio::ssl::context::sslv23);
ssl_ctx.set_default_verify_paths();
ssl_ctx.add_verify_path("/etc/ssl/certs");
ssl_ctx.set_verify_callback(boost::asio::ssl::rfc2818_verification(url.get_host()));
ssl_ctx.set_verify_mode(boost::asio::ssl::verify_peer|boost::asio::ssl::verify_fail_if_no_peer_cert);
boost::asio::ip::tcp::resolver resolver_(io);
using tcp_socket = boost::asio::ip::tcp::socket;
using ssl_socket = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>;
tcp_socket* tcp_layer = nullptr;
std::optional<std::variant<tcp_socket, ssl_socket>> http_stream;
boost::beast::flat_buffer buffer_; // (Must persist between reads)
boost::beast::http::request<boost::beast::http::string_body> req_;
boost::beast::http::response<boost::beast::http::string_body> res_;
// parse post_url to get host
req_.version(11);
req_.method(boost::beast::http::verb::post);
req_.target(post_url);
req_.set(boost::beast::http::field::host, url.get_host());
req_.set(boost::beast::http::field::user_agent, BOOST_BEAST_VERSION_STRING);
req_.set(boost::beast::http::field::content_type, content_type);
if (url.schema == "https") // use SSL here.
{
// inplace construct
http_stream.emplace(std::in_place_type<ssl_socket>, io, ssl_ctx);
ssl_socket& ssl_sock = std::get<1>(*http_stream);
// Let SSL have SNI capability
SSL_set_tlsext_host_name(ssl_sock.native_handle(), url.get_host().c_str());
tcp_layer = & ssl_sock.next_layer();
}
else
{
// inplace construct
http_stream.emplace(std::in_place_type<tcp_socket>, io);
tcp_layer = &(std::get<0>(*http_stream));
}
std::visit([&resolver_, &tcp_layer, &url](auto&& host)
{
using T = std::decay_t<decltype(host)>;
if constexpr (std::is_same_v<T, boost::asio::ip::address>)
{
tcp_layer->connect(boost::asio::ip::tcp::endpoint(host, (unsigned short)(url.port ? *url.port : ( url.schema == "https" ? 443 : 80))));
}
else
{
boost::asio::ip::tcp::resolver::results_type dns_result = resolver_.resolve(url.get_host(), std::to_string(url.port ? *url.port : ( url.schema == "https" ? 443 : 80)));
boost::asio::connect(*tcp_layer, dns_result.begin(), dns_result.end());
}
}, url.host);
if (url.schema == "https")
{
ssl_socket& ssl_stream = std::get<1>(*http_stream);
boost::system::error_code ec;
ssl_stream.handshake(boost::asio::ssl::stream_base::client);
}
req_.body() = post_content;
req_.prepare_payload();
// Send the HTTP request to the remote host
std::visit([&req_, &buffer_, &res_](auto && socket_)
{
boost::beast::http::write(socket_, req_);
boost::beast::http::read(socket_, buffer_, res_);
}, *http_stream);
return res_.body();
}
catch(std::runtime_error& e)
{
}
catch(std::exception& e)
{
}
return "";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment