]> git.proxmox.com Git - ceph.git/blame - ceph/src/Beast/examples/http_sync_server.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / examples / http_sync_server.hpp
CommitLineData
7c673cae
FG
1//
2// Copyright (c) 2013-2017 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
8#ifndef BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
9#define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
10
11#include "file_body.hpp"
12#include "mime_type.hpp"
13
14#include <beast/http.hpp>
15#include <beast/core/placeholders.hpp>
16#include <beast/core/streambuf.hpp>
17#include <boost/asio.hpp>
18#include <cstdint>
19#include <cstdio>
20#include <functional>
21#include <iostream>
22#include <memory>
23#include <mutex>
24#include <thread>
25#include <utility>
26
27#include <iostream>
28
29namespace beast {
30namespace http {
31
32class http_sync_server
33{
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;
37
38 using req_type = request<string_body>;
39 using resp_type = response<file_body>;
40
41 bool log_ = true;
42 std::mutex m_;
43 boost::asio::io_service ios_;
44 socket_type sock_;
45 boost::asio::ip::tcp::acceptor acceptor_;
46 std::string root_;
47 std::thread thread_;
48
49public:
50 http_sync_server(endpoint_type const& ep,
51 std::string const& root)
52 : sock_(ios_)
53 , acceptor_(ios_)
54 , root_(root)
55 {
56 acceptor_.open(ep.protocol());
57 acceptor_.bind(ep);
58 acceptor_.listen(
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(); }};
64 }
65
66 ~http_sync_server()
67 {
68 error_code ec;
69 ios_.dispatch(
70 [&]{ acceptor_.close(ec); });
71 thread_.join();
72 }
73
74 template<class... Args>
75 void
76 log(Args const&... args)
77 {
78 if(log_)
79 {
80 std::lock_guard<std::mutex> lock(m_);
81 log_args(args...);
82 }
83 }
84
85private:
86 void
87 log_args()
88 {
89 }
90
91 template<class Arg, class... Args>
92 void
93 log_args(Arg const& arg, Args const&... args)
94 {
95 std::cerr << arg;
96 log_args(args...);
97 }
98
99 void
100 fail(error_code ec, std::string what)
101 {
102 log(what, ": ", ec.message(), "\n");
103 }
104
105 void
106 fail(int id, error_code const& ec)
107 {
108 if(ec != boost::asio::error::operation_aborted &&
109 ec != boost::asio::error::eof)
110 log("#", id, " ", ec.message(), "\n");
111 }
112
113 struct lambda
114 {
115 int id;
116 http_sync_server& self;
117 socket_type sock;
118 boost::asio::io_service::work work;
119
120 lambda(int id_, http_sync_server& self_,
121 socket_type&& sock_)
122 : id(id_)
123 , self(self_)
124 , sock(std::move(sock_))
125 , work(sock.get_io_service())
126 {
127 }
128
129 void operator()()
130 {
131 self.do_peer(id, std::move(sock));
132 }
133 };
134
135 void
136 on_accept(error_code ec)
137 {
138 if(! acceptor_.is_open())
139 return;
140 if(ec)
141 return fail(ec, "accept");
142 static int id_ = 0;
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));
147 }
148
149 void
150 do_peer(int id, socket_type&& sock0)
151 {
152 socket_type sock(std::move(sock0));
153 streambuf sb;
154 error_code ec;
155 for(;;)
156 {
157 req_type req;
158 http::read(sock, sb, req, ec);
159 if(ec)
160 break;
161 auto path = req.url;
162 if(path == "/")
163 path = "/index.html";
164 path = root_ + path;
165 if(! boost::filesystem::exists(path))
166 {
167 response<string_body> res;
168 res.status = 404;
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";
174 prepare(res);
175 write(sock, res, ec);
176 if(ec)
177 break;
178 return;
179 }
180 try
181 {
182 resp_type res;
183 res.status = 200;
184 res.reason = "OK";
185 res.version = req.version;
186 res.fields.insert("Server", "http_sync_server");
187 res.fields.insert("Content-Type", mime_type(path));
188 res.body = path;
189 prepare(res);
190 write(sock, res, ec);
191 if(ec)
192 break;
193 }
194 catch(std::exception const& e)
195 {
196 response<string_body> res;
197 res.status = 500;
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");
202 res.body =
203 std::string{"An internal error occurred: "} + e.what();
204 prepare(res);
205 write(sock, res, ec);
206 if(ec)
207 break;
208 }
209 }
210 fail(id, ec);
211 }
212};
213
214} // http
215} // beast
216
217#endif