]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/example/http/client/async/http_client_async.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / example / http / client / async / http_client_async.cpp
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(
79 &session::on_resolve,
80 shared_from_this()));
81 }
82
83 void
84 on_resolve(
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(
98 &session::on_connect,
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(
114 &session::on_write,
115 shared_from_this()));
116 }
117
118 void
119 on_write(
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(
131 &session::on_read,
132 shared_from_this()));
133 }
134
135 void
136 on_read(
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 }