mirror of
https://github.com/boostorg/beast.git
synced 2025-07-29 20:37:31 +02:00
Use timeouts in HTTP client examples
This commit is contained in:
@ -3,6 +3,7 @@ Version 213:
|
||||
* Fix posix_file::close handling of EINTR
|
||||
* basic_stream subsumes stranded_stream:
|
||||
* Use timeouts in HTTP server examples
|
||||
* Use timeouts in HTTP client examples
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -18,10 +18,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/error.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/beast/_experimental/core/ssl_stream.hpp>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@ -36,6 +33,10 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
using stream_type =
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -47,7 +48,7 @@ fail(beast::error_code ec, char const* what)
|
||||
class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
tcp::resolver resolver_;
|
||||
ssl::stream<tcp::socket> stream_;
|
||||
stream_type stream_;
|
||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||
http::request<http::empty_body> req_;
|
||||
http::response<http::string_body> res_;
|
||||
@ -103,11 +104,13 @@ public:
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Set a timeout on the operation
|
||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
net::async_connect(
|
||||
stream_.next_layer(),
|
||||
results.begin(),
|
||||
results.end(),
|
||||
beast::async_connect(
|
||||
beast::get_lowest_layer(stream_),
|
||||
results,
|
||||
std::bind(
|
||||
&session::on_connect,
|
||||
shared_from_this(),
|
||||
@ -135,6 +138,9 @@ public:
|
||||
if(ec)
|
||||
return fail(ec, "handshake");
|
||||
|
||||
// Set a timeout on the operation
|
||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::async_write(stream_, req_,
|
||||
std::bind(
|
||||
@ -176,6 +182,9 @@ public:
|
||||
// Write the message to standard out
|
||||
std::cout << res_ << std::endl;
|
||||
|
||||
// Set a timeout on the operation
|
||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Gracefully close the stream
|
||||
stream_.async_shutdown(
|
||||
std::bind(
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@ -31,6 +29,9 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -42,7 +43,7 @@ fail(beast::error_code ec, char const* what)
|
||||
class session : public std::enable_shared_from_this<session>
|
||||
{
|
||||
tcp::resolver resolver_;
|
||||
tcp::socket socket_;
|
||||
stream_type stream_;
|
||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||
http::request<http::empty_body> req_;
|
||||
http::response<http::string_body> res_;
|
||||
@ -52,7 +53,7 @@ public:
|
||||
explicit
|
||||
session(net::io_context& ioc)
|
||||
: resolver_(ioc)
|
||||
, socket_(ioc)
|
||||
, stream_(ioc)
|
||||
{
|
||||
}
|
||||
|
||||
@ -90,11 +91,13 @@ public:
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Set a timeout on the operation
|
||||
stream_.expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
net::async_connect(
|
||||
socket_,
|
||||
results.begin(),
|
||||
results.end(),
|
||||
beast::async_connect(
|
||||
stream_,
|
||||
results,
|
||||
std::bind(
|
||||
&session::on_connect,
|
||||
shared_from_this(),
|
||||
@ -107,8 +110,11 @@ public:
|
||||
if(ec)
|
||||
return fail(ec, "connect");
|
||||
|
||||
// Set a timeout on the operation
|
||||
stream_.expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::async_write(socket_, req_,
|
||||
http::async_write(stream_, req_,
|
||||
std::bind(
|
||||
&session::on_write,
|
||||
shared_from_this(),
|
||||
@ -127,7 +133,7 @@ public:
|
||||
return fail(ec, "write");
|
||||
|
||||
// Receive the HTTP response
|
||||
http::async_read(socket_, buffer_, res_,
|
||||
http::async_read(stream_, buffer_, res_,
|
||||
std::bind(
|
||||
&session::on_read,
|
||||
shared_from_this(),
|
||||
@ -149,7 +155,7 @@ public:
|
||||
std::cout << res_ << std::endl;
|
||||
|
||||
// Gracefully close the socket
|
||||
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
||||
stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||
|
||||
// not_connected happens sometimes so don't bother reporting it.
|
||||
if(ec && ec != beast::errc::not_connected)
|
||||
|
@ -18,11 +18,8 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/beast/_experimental/core/ssl_stream.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/error.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@ -36,6 +33,11 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use
|
||||
// Stackful coroutines are already stranded.
|
||||
using stream_type =
|
||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -57,8 +59,8 @@ do_session(
|
||||
beast::error_code ec;
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ioc};
|
||||
ssl::stream<tcp::socket> stream{ioc, ctx};
|
||||
tcp::resolver resolver(ioc);
|
||||
stream_type stream(ioc, ctx);
|
||||
|
||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||
if(! SSL_set_tlsext_host_name(stream.native_handle(), host.c_str()))
|
||||
@ -73,11 +75,17 @@ do_session(
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Set the timeout.
|
||||
beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
net::async_connect(stream.next_layer(), results.begin(), results.end(), yield[ec]);
|
||||
beast::async_connect(get_lowest_layer(stream), results, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "connect");
|
||||
|
||||
// Set the timeout.
|
||||
beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Perform the SSL handshake
|
||||
stream.async_handshake(ssl::stream_base::client, yield[ec]);
|
||||
if(ec)
|
||||
@ -88,6 +96,9 @@ do_session(
|
||||
req.set(http::field::host, host);
|
||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||
|
||||
// Set the timeout.
|
||||
beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::async_write(stream, req, yield[ec]);
|
||||
if(ec)
|
||||
@ -107,6 +118,9 @@ do_session(
|
||||
// Write the message to standard out
|
||||
std::cout << res << std::endl;
|
||||
|
||||
// Set the timeout.
|
||||
beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Gracefully close the stream
|
||||
stream.async_shutdown(yield[ec]);
|
||||
if(ec == net::error::eof)
|
||||
|
@ -16,9 +16,7 @@
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@ -31,6 +29,10 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The type of stream to use.
|
||||
// Stackful coroutines are already stranded.
|
||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
||||
|
||||
// Report a failure
|
||||
void
|
||||
fail(beast::error_code ec, char const* what)
|
||||
@ -52,15 +54,18 @@ do_session(
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver{ioc};
|
||||
tcp::socket socket{ioc};
|
||||
stream_type stream(ioc);
|
||||
|
||||
// Look up the domain name
|
||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "resolve");
|
||||
|
||||
// Set the timeout.
|
||||
stream.expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
net::async_connect(socket, results.begin(), results.end(), yield[ec]);
|
||||
beast::async_connect(stream, results, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "connect");
|
||||
|
||||
@ -69,8 +74,11 @@ do_session(
|
||||
req.set(http::field::host, host);
|
||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||
|
||||
// Set the timeout.
|
||||
stream.expires_after(std::chrono::seconds(30));
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::async_write(socket, req, yield[ec]);
|
||||
http::async_write(stream, req, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "write");
|
||||
|
||||
@ -81,7 +89,7 @@ do_session(
|
||||
http::response<http::dynamic_body> res;
|
||||
|
||||
// Receive the HTTP response
|
||||
http::async_read(socket, b, res, yield[ec]);
|
||||
http::async_read(stream, b, res, yield[ec]);
|
||||
if(ec)
|
||||
return fail(ec, "read");
|
||||
|
||||
@ -89,7 +97,7 @@ do_session(
|
||||
std::cout << res << std::endl;
|
||||
|
||||
// Gracefully close the socket
|
||||
socket.shutdown(tcp::socket::shutdown_both, ec);
|
||||
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||
|
||||
// not_connected happens sometimes
|
||||
// so don't bother reporting it.
|
||||
|
Reference in New Issue
Block a user