| 38 | } |
| 39 | |
| 40 | net::awaitable<void> |
| 41 | request(ssl::context& ctx) |
| 42 | { |
| 43 | auto executor = co_await net::this_coro::executor; |
| 44 | net::ip::tcp::endpoint endpoint{ {}, 8080 }; |
| 45 | ssl::stream<net::ip::tcp::socket> stream{ executor, ctx }; |
| 46 | |
| 47 | // Connect TCP socket |
| 48 | co_await stream.lowest_layer().async_connect(endpoint); |
| 49 | |
| 50 | // Set Server Name Indication (SNI) |
| 51 | if(!SSL_set_tlsext_host_name(stream.native_handle(), "localhost")) |
| 52 | { |
| 53 | throw beast::system_error( |
| 54 | static_cast<int>(::ERR_get_error()), |
| 55 | net::error::get_ssl_category()); |
| 56 | } |
| 57 | |
| 58 | // Set a callback to verify that the hostname in the server |
| 59 | // certificate matches the expected value |
| 60 | stream.set_verify_callback(ssl::host_name_verification("localhost")); |
| 61 | |
| 62 | // Perform the SSL handshake |
| 63 | co_await stream.async_handshake(ssl::stream_base::client); |
| 64 | |
| 65 | // Write an HTTP GET request |
| 66 | http::request<http::empty_body> req{ http::verb::get, "/", 11 }; |
| 67 | req.set(http::field::host, "localhost"); |
| 68 | req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); |
| 69 | co_await http::async_write(stream, req); |
| 70 | |
| 71 | // Read the response |
| 72 | beast::flat_buffer buf; |
| 73 | http::response<http::string_body> res; |
| 74 | co_await http::async_read(stream, buf, res); |
| 75 | |
| 76 | // Print the response body |
| 77 | std::cout << res.body(); |
| 78 | |
| 79 | // Gracefully shutdown the SSL stream |
| 80 | auto [ec] = co_await stream.async_shutdown(net::as_tuple); |
| 81 | if(ec && ec != ssl::error::stream_truncated) |
| 82 | throw boost::system::system_error(ec); |
| 83 | } |
| 84 | |
| 85 | int |
| 86 | main() |
no test coverage detected