Last active
July 2, 2019 05:51
-
-
Save microcai/08b813e588a1eb1c966fd555d3f22eb3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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