]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/beast/example/http/server/coro/http_server_coro.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / example / http / server / coro / http_server_coro.cpp
index 988a022181259b99dc3fb7a35cb32d52dfe6f1e8..a8baae640064325501351b0a3659a07092e7c93c 100644 (file)
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 #include <thread>
 #include <vector>
 
+namespace beast = boost::beast;         // from <boost/beast.hpp>
+namespace http = beast::http;           // from <boost/beast/http.hpp>
+namespace net = boost::asio;            // from <boost/asio.hpp>
 using tcp = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>
-namespace http = boost::beast::http;    // from <boost/beast/http.hpp>
 
 // Return a reasonable mime type based on the extension of a file.
-boost::beast::string_view
-mime_type(boost::beast::string_view path)
+beast::string_view
+mime_type(beast::string_view path)
 {
-    using boost::beast::iequals;
+    using beast::iequals;
     auto const ext = [&path]
     {
         auto const pos = path.rfind(".");
-        if(pos == boost::beast::string_view::npos)
-            return boost::beast::string_view{};
+        if(pos == beast::string_view::npos)
+            return beast::string_view{};
         return path.substr(pos);
     }();
     if(iequals(ext, ".htm"))  return "text/html";
@@ -70,13 +72,13 @@ mime_type(boost::beast::string_view path)
 // The returned path is normalized for the platform.
 std::string
 path_cat(
-    boost::beast::string_view base,
-    boost::beast::string_view path)
+    beast::string_view base,
+    beast::string_view path)
 {
     if(base.empty())
-        return path.to_string();
-    std::string result = base.to_string();
-#if BOOST_MSVC
+        return std::string(path);
+    std::string result(base);
+#ifdef BOOST_MSVC
     char constexpr path_separator = '\\';
     if(result.back() == path_separator)
         result.resize(result.size() - 1);
@@ -102,45 +104,45 @@ template<
     class Send>
 void
 handle_request(
-    boost::beast::string_view doc_root,
+    beast::string_view doc_root,
     http::request<Body, http::basic_fields<Allocator>>&& req,
     Send&& send)
 {
     // Returns a bad request response
     auto const bad_request =
-    [&req](boost::beast::string_view why)
+    [&req](beast::string_view why)
     {
         http::response<http::string_body> res{http::status::bad_request, req.version()};
         res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
         res.set(http::field::content_type, "text/html");
         res.keep_alive(req.keep_alive());
-        res.body() = why.to_string();
+        res.body() = std::string(why);
         res.prepare_payload();
         return res;
     };
 
     // Returns a not found response
     auto const not_found =
-    [&req](boost::beast::string_view target)
+    [&req](beast::string_view target)
     {
         http::response<http::string_body> res{http::status::not_found, req.version()};
         res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
         res.set(http::field::content_type, "text/html");
         res.keep_alive(req.keep_alive());
-        res.body() = "The resource '" + target.to_string() + "' was not found.";
+        res.body() = "The resource '" + std::string(target) + "' was not found.";
         res.prepare_payload();
         return res;
     };
 
     // Returns a server error response
     auto const server_error =
-    [&req](boost::beast::string_view what)
+    [&req](beast::string_view what)
     {
         http::response<http::string_body> res{http::status::internal_server_error, req.version()};
         res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
         res.set(http::field::content_type, "text/html");
         res.keep_alive(req.keep_alive());
-        res.body() = "An error occurred: '" + what.to_string() + "'";
+        res.body() = "An error occurred: '" + std::string(what) + "'";
         res.prepare_payload();
         return res;
     };
@@ -153,7 +155,7 @@ handle_request(
     // Request path must be absolute and not contain "..".
     if( req.target().empty() ||
         req.target()[0] != '/' ||
-        req.target().find("..") != boost::beast::string_view::npos)
+        req.target().find("..") != beast::string_view::npos)
         return send(bad_request("Illegal request-target"));
 
     // Build the path to the requested file
@@ -162,12 +164,12 @@ handle_request(
         path.append("index.html");
 
     // Attempt to open the file
-    boost::beast::error_code ec;
+    beast::error_code ec;
     http::file_body::value_type body;
-    body.open(path.c_str(), boost::beast::file_mode::scan, ec);
+    body.open(path.c_str(), beast::file_mode::scan, ec);
 
     // Handle the case where the file doesn't exist
-    if(ec == boost::system::errc::no_such_file_or_directory)
+    if(ec == beast::errc::no_such_file_or_directory)
         return send(not_found(req.target()));
 
     // Handle an unknown error
@@ -204,27 +206,25 @@ handle_request(
 
 // Report a failure
 void
-fail(boost::system::error_code ec, char const* what)
+fail(beast::error_code ec, char const* what)
 {
     std::cerr << what << ": " << ec.message() << "\n";
 }
 
 // This is the C++11 equivalent of a generic lambda.
 // The function object is used to send an HTTP message.
-template<class Stream>
 struct send_lambda
 {
-    Stream& stream_;
+    beast::tcp_stream& stream_;
     bool& close_;
-    boost::system::error_code& ec_;
-    boost::asio::yield_context yield_;
+    beast::error_code& ec_;
+    net::yield_context yield_;
 
-    explicit
     send_lambda(
-        Stream& stream,
+        beast::tcp_stream& stream,
         bool& close,
-        boost::system::error_code& ec,
-        boost::asio::yield_context yield)
+        beast::error_code& ec,
+        net::yield_context yield)
         : stream_(stream)
         , close_(close)
         , ec_(ec)
@@ -250,31 +250,34 @@ struct send_lambda
 // Handles an HTTP server connection
 void
 do_session(
-    tcp::socket& socket,
-    std::string const& doc_root,
-    boost::asio::yield_context yield)
+    beast::tcp_stream& stream,
+    std::shared_ptr<std::string const> const& doc_root,
+    net::yield_context yield)
 {
     bool close = false;
-    boost::system::error_code ec;
+    beast::error_code ec;
 
     // This buffer is required to persist across reads
-    boost::beast::flat_buffer buffer;
+    beast::flat_buffer buffer;
 
     // This lambda is used to send messages
-    send_lambda<tcp::socket> lambda{socket, close, ec, yield};
+    send_lambda lambda{stream, close, ec, yield};
 
     for(;;)
     {
+        // Set the timeout.
+        stream.expires_after(std::chrono::seconds(30));
+
         // Read a request
         http::request<http::string_body> req;
-        http::async_read(socket, buffer, req, yield[ec]);
+        http::async_read(stream, buffer, req, yield[ec]);
         if(ec == http::error::end_of_stream)
             break;
         if(ec)
             return fail(ec, "read");
 
         // Send the response
-        handle_request(doc_root, std::move(req), lambda);
+        handle_request(*doc_root, std::move(req), lambda);
         if(ec)
             return fail(ec, "write");
         if(close)
@@ -286,7 +289,7 @@ do_session(
     }
 
     // Send a TCP shutdown
-    socket.shutdown(tcp::socket::shutdown_send, ec);
+    stream.socket().shutdown(tcp::socket::shutdown_send, ec);
 
     // At this point the connection is closed gracefully
 }
@@ -296,12 +299,12 @@ do_session(
 // Accepts incoming connections and launches the sessions
 void
 do_listen(
-    boost::asio::io_context& ioc,
+    net::io_context& ioc,
     tcp::endpoint endpoint,
-    std::string const& doc_root,
-    boost::asio::yield_context yield)
+    std::shared_ptr<std::string const> const& doc_root,
+    net::yield_context yield)
 {
-    boost::system::error_code ec;
+    beast::error_code ec;
 
     // Open the acceptor
     tcp::acceptor acceptor(ioc);
@@ -310,7 +313,7 @@ do_listen(
         return fail(ec, "open");
 
     // Allow address reuse
-    acceptor.set_option(boost::asio::socket_base::reuse_address(true));
+    acceptor.set_option(net::socket_base::reuse_address(true), ec);
     if(ec)
         return fail(ec, "set_option");
 
@@ -320,7 +323,7 @@ do_listen(
         return fail(ec, "bind");
 
     // Start listening for connections
-    acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
+    acceptor.listen(net::socket_base::max_listen_connections, ec);
     if(ec)
         return fail(ec, "listen");
 
@@ -332,10 +335,10 @@ do_listen(
             fail(ec, "accept");
         else
             boost::asio::spawn(
-                acceptor.get_executor().context(),
+                acceptor.get_executor(),
                 std::bind(
                     &do_session,
-                    std::move(socket),
+                    beast::tcp_stream(std::move(socket)),
                     doc_root,
                     std::placeholders::_1));
     }
@@ -352,13 +355,13 @@ int main(int argc, char* argv[])
             "    http-server-coro 0.0.0.0 8080 . 1\n";
         return EXIT_FAILURE;
     }
-    auto const address = boost::asio::ip::make_address(argv[1]);
+    auto const address = net::ip::make_address(argv[1]);
     auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
-    std::string const doc_root = argv[3];
+    auto const doc_root = std::make_shared<std::string>(argv[3]);
     auto const threads = std::max<int>(1, std::atoi(argv[4]));
 
     // The io_context is required for all I/O
-    boost::asio::io_context ioc{threads};
+    net::io_context ioc{threads};
 
     // Spawn a listening port
     boost::asio::spawn(ioc,