18 #include <boost/beast/core.hpp>
19 #include <boost/beast/http.hpp>
20 #include <boost/beast/ssl.hpp>
21 #include <boost/beast/version.hpp>
22 #include <boost/asio/strand.hpp>
29 namespace beast = boost::beast;
30 namespace http = beast::http;
31 namespace net = boost::asio;
32 namespace ssl = boost::asio::ssl;
39 fail(beast::error_code ec,
char const* what)
41 std::cerr << what <<
": " << ec.message() <<
"\n";
45 class session :
public std::enable_shared_from_this<session>
48 beast::ssl_stream<beast::tcp_stream>
stream_;
50 http::request<http::empty_body>
req_;
51 http::response<http::string_body>
res_;
72 if(! SSL_set_tlsext_host_name(
stream_.native_handle(), host))
74 beast::error_code ec{
static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()};
75 std::cerr << ec.message() <<
"\n";
80 req_.version(version);
83 req_.set(http::field::host, host);
84 req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
90 beast::bind_front_handler(
98 tcp::resolver::results_type results)
101 return fail(ec,
"resolve");
104 beast::get_lowest_layer(
stream_).expires_after(std::chrono::seconds(30));
107 beast::get_lowest_layer(
stream_).async_connect(
109 beast::bind_front_handler(
111 shared_from_this()));
115 on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
118 return fail(ec,
"connect");
122 ssl::stream_base::client,
123 beast::bind_front_handler(
125 shared_from_this()));
132 return fail(ec,
"handshake");
135 beast::get_lowest_layer(
stream_).expires_after(std::chrono::seconds(30));
139 beast::bind_front_handler(
141 shared_from_this()));
146 beast::error_code ec,
147 std::size_t bytes_transferred)
149 boost::ignore_unused(bytes_transferred);
152 return fail(ec,
"write");
156 beast::bind_front_handler(
158 shared_from_this()));
163 beast::error_code ec,
164 std::size_t bytes_transferred)
166 boost::ignore_unused(bytes_transferred);
169 return fail(ec,
"read");
172 std::cout <<
res_ << std::endl;
175 beast::get_lowest_layer(
stream_).expires_after(std::chrono::seconds(30));
179 beast::bind_front_handler(
181 shared_from_this()));
187 if(ec == net::error::eof)
194 return fail(ec,
"shutdown");
202 int main(
int argc,
char** argv)
205 if(argc != 4 && argc != 5)
208 "Usage: http-client-async-ssl <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
210 " http-client-async-ssl www.example.com 443 /\n" <<
211 " http-client-async-ssl www.example.com 443 / 1.0\n";
214 auto const host = argv[1];
215 auto const port = argv[2];
216 auto const target = argv[3];
217 int version = argc == 5 && !std::strcmp(
"1.0", argv[4]) ? 10 : 11;
223 ssl::context ctx{ssl::context::tlsv12_client};
229 ctx.set_verify_mode(ssl::verify_peer);
234 std::make_shared<session>(
235 net::make_strand(ioc),
237 )->run(host, port,
target, version);