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