2 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail 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)
8 #ifndef BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
9 #define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
11 #include "file_body.hpp"
12 #include "mime_type.hpp"
14 #include <beast/http.hpp>
15 #include <beast/core/placeholders.hpp>
16 #include <beast/core/streambuf.hpp>
17 #include <boost/asio.hpp>
32 class http_sync_server
34 using endpoint_type = boost::asio::ip::tcp::endpoint;
35 using address_type = boost::asio::ip::address;
36 using socket_type = boost::asio::ip::tcp::socket;
38 using req_type = request<string_body>;
39 using resp_type = response<file_body>;
43 boost::asio::io_service ios_;
45 boost::asio::ip::tcp::acceptor acceptor_;
50 http_sync_server(endpoint_type const& ep,
51 std::string const& root)
56 acceptor_.open(ep.protocol());
59 boost::asio::socket_base::max_connections);
60 acceptor_.async_accept(sock_,
61 std::bind(&http_sync_server::on_accept, this,
62 beast::asio::placeholders::error));
63 thread_ = std::thread{[&]{ ios_.run(); }};
70 [&]{ acceptor_.close(ec); });
74 template<class... Args>
76 log(Args const&... args)
80 std::lock_guard<std::mutex> lock(m_);
91 template<class Arg, class... Args>
93 log_args(Arg const& arg, Args const&... args)
100 fail(error_code ec, std::string what)
102 log(what, ": ", ec.message(), "\n");
106 fail(int id, error_code const& ec)
108 if(ec != boost::asio::error::operation_aborted &&
109 ec != boost::asio::error::eof)
110 log("#", id, " ", ec.message(), "\n");
116 http_sync_server& self;
118 boost::asio::io_service::work work;
120 lambda(int id_, http_sync_server& self_,
124 , sock(std::move(sock_))
125 , work(sock.get_io_service())
131 self.do_peer(id, std::move(sock));
136 on_accept(error_code ec)
138 if(! acceptor_.is_open())
141 return fail(ec, "accept");
143 std::thread{lambda{++id_, *this, std::move(sock_)}}.detach();
144 acceptor_.async_accept(sock_,
145 std::bind(&http_sync_server::on_accept, this,
146 asio::placeholders::error));
150 do_peer(int id, socket_type&& sock0)
152 socket_type sock(std::move(sock0));
158 http::read(sock, sb, req, ec);
163 path = "/index.html";
165 if(! boost::filesystem::exists(path))
167 response<string_body> res;
169 res.reason = "Not Found";
170 res.version = req.version;
171 res.fields.insert("Server", "http_sync_server");
172 res.fields.insert("Content-Type", "text/html");
173 res.body = "The file '" + path + "' was not found";
175 write(sock, res, ec);
185 res.version = req.version;
186 res.fields.insert("Server", "http_sync_server");
187 res.fields.insert("Content-Type", mime_type(path));
190 write(sock, res, ec);
194 catch(std::exception const& e)
196 response<string_body> res;
198 res.reason = "Internal Error";
199 res.version = req.version;
200 res.fields.insert("Server", "http_sync_server");
201 res.fields.insert("Content-Type", "text/html");
203 std::string{"An internal error occurred: "} + e.what();
205 write(sock, res, ec);