MEPP2 Project
http_client_async.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 //------------------------------------------------------------------------------
11 //
12 // Example: HTTP client, asynchronous
13 //
14 //------------------------------------------------------------------------------
15 
16 #include <boost/beast/core.hpp>
17 #include <boost/beast/http.hpp>
18 #include <boost/beast/version.hpp>
19 #include <boost/asio/strand.hpp>
20 #include <cstdlib>
21 #include <functional>
22 #include <iostream>
23 #include <memory>
24 #include <string>
25 
26 namespace beast = boost::beast; // from <boost/beast.hpp>
27 namespace http = beast::http; // from <boost/beast/http.hpp>
28 namespace net = boost::asio; // from <boost/asio.hpp>
29 using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
30 
31 //------------------------------------------------------------------------------
32 
33 // Report a failure
34 void
35 fail(beast::error_code ec, char const* what)
36 {
37  std::cerr << what << ": " << ec.message() << "\n";
38 }
39 
40 // Performs an HTTP GET and prints the response
41 class session : public std::enable_shared_from_this<session>
42 {
43  tcp::resolver resolver_;
44  beast::tcp_stream stream_;
45  beast::flat_buffer buffer_; // (Must persist between reads)
46  http::request<http::empty_body> req_;
47  http::response<http::string_body> res_;
48 
49 public:
50  // Objects are constructed with a strand to
51  // ensure that handlers do not execute concurrently.
52  explicit
53  session(net::io_context& ioc)
54  : resolver_(net::make_strand(ioc))
55  , stream_(net::make_strand(ioc))
56  {
57  }
58 
59  // Start the asynchronous operation
60  void
61  run(
62  char const* host,
63  char const* port,
64  char const* target,
65  int version)
66  {
67  // Set up an HTTP GET request message
68  req_.version(version);
69  req_.method(http::verb::get);
70  req_.target(target);
71  req_.set(http::field::host, host);
72  req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
73 
74  // Look up the domain name
75  resolver_.async_resolve(
76  host,
77  port,
78  beast::bind_front_handler(
80  shared_from_this()));
81  }
82 
83  void
85  beast::error_code ec,
86  tcp::resolver::results_type results)
87  {
88  if(ec)
89  return fail(ec, "resolve");
90 
91  // Set a timeout on the operation
92  stream_.expires_after(std::chrono::seconds(30));
93 
94  // Make the connection on the IP address we get from a lookup
95  stream_.async_connect(
96  results,
97  beast::bind_front_handler(
99  shared_from_this()));
100  }
101 
102  void
103  on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
104  {
105  if(ec)
106  return fail(ec, "connect");
107 
108  // Set a timeout on the operation
109  stream_.expires_after(std::chrono::seconds(30));
110 
111  // Send the HTTP request to the remote host
112  http::async_write(stream_, req_,
113  beast::bind_front_handler(
115  shared_from_this()));
116  }
117 
118  void
120  beast::error_code ec,
121  std::size_t bytes_transferred)
122  {
123  boost::ignore_unused(bytes_transferred);
124 
125  if(ec)
126  return fail(ec, "write");
127 
128  // Receive the HTTP response
129  http::async_read(stream_, buffer_, res_,
130  beast::bind_front_handler(
132  shared_from_this()));
133  }
134 
135  void
137  beast::error_code ec,
138  std::size_t bytes_transferred)
139  {
140  boost::ignore_unused(bytes_transferred);
141 
142  if(ec)
143  return fail(ec, "read");
144 
145  // Write the message to standard out
146  std::cout << res_ << std::endl;
147 
148  // Gracefully close the socket
149  stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
150 
151  // not_connected happens sometimes so don't bother reporting it.
152  if(ec && ec != beast::errc::not_connected)
153  return fail(ec, "shutdown");
154 
155  // If we get here then the connection is closed gracefully
156  }
157 };
158 
159 //------------------------------------------------------------------------------
160 
161 int main(int argc, char** argv)
162 {
163  // Check command line arguments.
164  if(argc != 4 && argc != 5)
165  {
166  std::cerr <<
167  "Usage: http-client-async <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
168  "Example:\n" <<
169  " http-client-async www.example.com 80 /\n" <<
170  " http-client-async www.example.com 80 / 1.0\n";
171  return EXIT_FAILURE;
172  }
173  auto const host = argv[1];
174  auto const port = argv[2];
175  auto const target = argv[3];
176  int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
177 
178  // The io_context is required for all I/O
179  net::io_context ioc;
180 
181  // Launch the asynchronous operation
182  std::make_shared<session>(ioc)->run(host, port, target, version);
183 
184  // Run the I/O service. The call will return when
185  // the get operation is complete.
186  ioc.run();
187 
188  return EXIT_SUCCESS;
189 }
session::on_connect
void on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
Definition: http_client_async.cpp:103
session::session
session(net::io_context &ioc)
Definition: http_client_async.cpp:53
session::on_write
void on_write(beast::error_code ec, std::size_t bytes_transferred)
Definition: http_client_async.cpp:119
fail
void fail(beast::error_code ec, char const *what)
Definition: http_client_async.cpp:35
session
Definition: http_client_async.cpp:42
session::resolver_
tcp::resolver resolver_
Definition: http_client_async.cpp:43
session::run
void run(char const *host, char const *port, char const *target, int version)
Definition: http_client_async.cpp:61
main
int main(int argc, char **argv)
Definition: http_client_async.cpp:161
FEVV::DataStructures::AIF::target
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_descriptor target(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::edge_descriptor e, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the target vertex of e.
Definition: Graph_traits_aif.h:400
session::req_
http::request< http::empty_body > req_
Definition: http_client_async.cpp:46
session::on_resolve
void on_resolve(beast::error_code ec, tcp::resolver::results_type results)
Definition: http_client_async.cpp:84
session::stream_
beast::tcp_stream stream_
Definition: http_client_async.cpp:44
boost::get
boost::property_map< FEVV::DataStructures::AIF::AIFMesh, boost::vertex_index_t >::const_type get(const boost::vertex_index_t &, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the vertex index property map of the mesh.
Definition: Graph_properties_aif.h:108
session::on_read
void on_read(beast::error_code ec, std::size_t bytes_transferred)
Definition: http_client_async.cpp:136
session::res_
http::response< http::string_body > res_
Definition: http_client_async.cpp:47
tcp
boost::asio::ip::tcp tcp
Definition: http_client_async.cpp:29
session::buffer_
beast::flat_buffer buffer_
Definition: http_client_async.cpp:45