]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/example/http/server/small/http_server_small.cpp
2 // Copyright (c) 2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 //------------------------------------------------------------------------------
12 // Example: HTTP server, small
14 //------------------------------------------------------------------------------
16 #include <boost/beast/core.hpp>
17 #include <boost/beast/http.hpp>
18 #include <boost/beast/version.hpp>
19 #include <boost/asio.hpp>
27 namespace ip
= boost::asio::ip
; // from <boost/asio.hpp>
28 using tcp
= boost::asio::ip::tcp
; // from <boost/asio.hpp>
29 namespace http
= boost::beast::http
; // from <boost/beast/http.hpp>
31 namespace my_program_state
36 static std::size_t count
= 0;
47 class http_connection
: public std::enable_shared_from_this
<http_connection
>
50 http_connection(tcp::socket socket
)
51 : socket_(std::move(socket
))
55 // Initiate the asynchronous operations associated with the connection.
64 // The socket for the currently connected client.
67 // The buffer for performing reads.
68 boost::beast::flat_buffer buffer_
{8192};
70 // The request message.
71 http::request
<http::dynamic_body
> request_
;
73 // The response message.
74 http::response
<http::dynamic_body
> response_
;
76 // The timer for putting a deadline on connection processing.
77 boost::asio::basic_waitable_timer
<std::chrono::steady_clock
> deadline_
{
78 socket_
.get_executor().context(), std::chrono::seconds(60)};
80 // Asynchronously receive a complete request message.
84 auto self
= shared_from_this();
90 [self
](boost::beast::error_code ec
,
91 std::size_t bytes_transferred
)
93 boost::ignore_unused(bytes_transferred
);
95 self
->process_request();
99 // Determine what needs to be done with the request message.
103 response_
.version(request_
.version());
104 response_
.keep_alive(false);
106 switch(request_
.method())
108 case http::verb::get
:
109 response_
.result(http::status::ok
);
110 response_
.set(http::field::server
, "Beast");
115 // We return responses indicating an error if
116 // we do not recognize the request method.
117 response_
.result(http::status::bad_request
);
118 response_
.set(http::field::content_type
, "text/plain");
119 boost::beast::ostream(response_
.body())
120 << "Invalid request-method '"
121 << request_
.method_string().to_string()
129 // Construct a response message based on the program state.
133 if(request_
.target() == "/count")
135 response_
.set(http::field::content_type
, "text/html");
136 boost::beast::ostream(response_
.body())
138 << "<head><title>Request count</title></head>\n"
140 << "<h1>Request count</h1>\n"
141 << "<p>There have been "
142 << my_program_state::request_count()
143 << " requests so far.</p>\n"
147 else if(request_
.target() == "/time")
149 response_
.set(http::field::content_type
, "text/html");
150 boost::beast::ostream(response_
.body())
152 << "<head><title>Current time</title></head>\n"
154 << "<h1>Current time</h1>\n"
155 << "<p>The current time is "
156 << my_program_state::now()
157 << " seconds since the epoch.</p>\n"
163 response_
.result(http::status::not_found
);
164 response_
.set(http::field::content_type
, "text/plain");
165 boost::beast::ostream(response_
.body()) << "File not found\r\n";
169 // Asynchronously transmit the response message.
173 auto self
= shared_from_this();
175 response_
.set(http::field::content_length
, response_
.body().size());
180 [self
](boost::beast::error_code ec
, std::size_t)
182 self
->socket_
.shutdown(tcp::socket::shutdown_send
, ec
);
183 self
->deadline_
.cancel();
187 // Check whether we have spent enough time on this connection.
191 auto self
= shared_from_this();
193 deadline_
.async_wait(
194 [self
](boost::beast::error_code ec
)
198 // Close socket to cancel any outstanding operation.
199 self
->socket_
.close(ec
);
205 // "Loop" forever accepting new connections.
207 http_server(tcp::acceptor
& acceptor
, tcp::socket
& socket
)
209 acceptor
.async_accept(socket
,
210 [&](boost::beast::error_code ec
)
213 std::make_shared
<http_connection
>(std::move(socket
))->start();
214 http_server(acceptor
, socket
);
219 main(int argc
, char* argv
[])
223 // Check command line arguments.
226 std::cerr
<< "Usage: " << argv
[0] << " <address> <port>\n";
227 std::cerr
<< " For IPv4, try:\n";
228 std::cerr
<< " receiver 0.0.0.0 80\n";
229 std::cerr
<< " For IPv6, try:\n";
230 std::cerr
<< " receiver 0::0 80\n";
234 auto const address
= boost::asio::ip::make_address(argv
[1]);
235 unsigned short port
= static_cast<unsigned short>(std::atoi(argv
[2]));
237 boost::asio::io_context ioc
{1};
239 tcp::acceptor acceptor
{ioc
, {address
, port
}};
240 tcp::socket socket
{ioc
};
241 http_server(acceptor
, socket
);
245 catch(std::exception
const& e
)
247 std::cerr
<< "Error: " << e
.what() << std::endl
;