Electroneum
crow.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <string>
4 #include <functional>
5 #include <memory>
6 #include <future>
7 #include <cstdint>
8 #include <type_traits>
9 #include <thread>
10 
11 #include "settings.h"
12 #include "logging.h"
13 #include "utility.h"
14 #include "routing.h"
15 #include "middleware_context.h"
16 #include "http_request.h"
17 #include "http_server.h"
18 
19 
20 #ifdef CROW_MSVC_WORKAROUND
21 #define CROW_ROUTE(app, url) app.route_dynamic(url)
22 #else
23 #define CROW_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url)
24 #endif
25 
26 namespace crow
27 {
28 #ifdef CROW_ENABLE_SSL
29  using ssl_context_t = boost::asio::ssl::context;
30 #endif
31  template <typename ... Middlewares>
32  class Crow
33  {
34  public:
35  using self_t = Crow;
36  using server_t = Server<Crow, SocketAdaptor, Middlewares...>;
37 #ifdef CROW_ENABLE_SSL
38  using ssl_server_t = Server<Crow, SSLAdaptor, Middlewares...>;
39 #endif
40  Crow()
41  {
42  }
43 
44  template <typename Adaptor>
45  void handle_upgrade(const request& req, response& res, Adaptor&& adaptor)
46  {
47  router_.handle_upgrade(req, res, adaptor);
48  }
49 
50  void handle(const request& req, response& res)
51  {
52  router_.handle(req, res);
53  }
54 
55  DynamicRule& route_dynamic(std::string&& rule)
56  {
57  return router_.new_rule_dynamic(std::move(rule));
58  }
59 
60  template <uint64_t Tag>
61  auto route(std::string&& rule)
62  -> typename std::result_of<decltype(&Router::new_rule_tagged<Tag>)(Router, std::string&&)>::type
63  {
64  return router_.new_rule_tagged<Tag>(std::move(rule));
65  }
66 
67  self_t& port(std::uint16_t port)
68  {
69  port_ = port;
70  return *this;
71  }
72 
73  self_t& bindaddr(std::string bindaddr)
74  {
76  return *this;
77  }
78 
80  {
81  return concurrency(std::thread::hardware_concurrency());
82  }
83 
84  self_t& concurrency(std::uint16_t concurrency)
85  {
86  if (concurrency < 1)
87  concurrency = 1;
89  return *this;
90  }
91 
92  void validate()
93  {
94  router_.validate();
95  }
96 
97  void run()
98  {
99  validate();
100 #ifdef CROW_ENABLE_SSL
101  if (use_ssl_)
102  {
103  ssl_server_ = std::move(std::unique_ptr<ssl_server_t>(new ssl_server_t(this, bindaddr_, port_, &middlewares_, concurrency_, &ssl_context_)));
104  ssl_server_->run();
105  }
106  else
107 #endif
108  {
109  server_ = std::move(std::unique_ptr<server_t>(new server_t(this, bindaddr_, port_, &middlewares_, concurrency_, nullptr)));
110  server_->run();
111  }
112  }
113 
114  void stop()
115  {
116 #ifdef CROW_ENABLE_SSL
117  if (use_ssl_)
118  {
119  ssl_server_->stop();
120  }
121  else
122 #endif
123  {
124  server_->stop();
125  }
126  }
127 
128  void debug_print()
129  {
130  CROW_LOG_DEBUG << "Routing:";
132  }
133 
134 #ifdef CROW_ENABLE_SSL
135  self_t& ssl_file(const std::string& crt_filename, const std::string& key_filename)
136  {
137  use_ssl_ = true;
138  ssl_context_.set_verify_mode(boost::asio::ssl::verify_peer);
139  ssl_context_.use_certificate_file(crt_filename, ssl_context_t::pem);
140  ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
141  ssl_context_.set_options(
142  boost::asio::ssl::context::default_workarounds
143  | boost::asio::ssl::context::no_sslv2
144  | boost::asio::ssl::context::no_sslv3
145  );
146  return *this;
147  }
148 
149  self_t& ssl_file(const std::string& pem_filename)
150  {
151  use_ssl_ = true;
152  ssl_context_.set_verify_mode(boost::asio::ssl::verify_peer);
153  ssl_context_.load_verify_file(pem_filename);
154  ssl_context_.set_options(
155  boost::asio::ssl::context::default_workarounds
156  | boost::asio::ssl::context::no_sslv2
157  | boost::asio::ssl::context::no_sslv3
158  );
159  return *this;
160  }
161 
163  {
164  use_ssl_ = true;
165  ssl_context_ = std::move(ctx);
166  return *this;
167  }
168 
169 
170  bool use_ssl_{false};
171  ssl_context_t ssl_context_{boost::asio::ssl::context::sslv23};
172 
173 #else
174  template <typename T, typename ... Remain>
175  self_t& ssl_file(T&&, Remain&&...)
176  {
177  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
178  static_assert(
179  // make static_assert dependent to T; always false
180  std::is_base_of<T, void>::value,
181  "Define CROW_ENABLE_SSL to enable ssl support.");
182  return *this;
183  }
184 
185  template <typename T>
187  {
188  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
189  static_assert(
190  // make static_assert dependent to T; always false
191  std::is_base_of<T, void>::value,
192  "Define CROW_ENABLE_SSL to enable ssl support.");
193  return *this;
194  }
195 #endif
196 
197  // middleware
198  using context_t = detail::context<Middlewares...>;
199  template <typename T>
200  typename T::context& get_context(const request& req)
201  {
202  static_assert(black_magic::contains<T, Middlewares...>::value, "App doesn't have the specified middleware type.");
203  auto& ctx = *reinterpret_cast<context_t*>(req.middleware_context);
204  return ctx.template get<T>();
205  }
206 
207  template <typename T>
209  {
210  return utility::get_element_by_type<T, Middlewares...>(middlewares_);
211  }
212 
213  private:
214  uint16_t port_ = 80;
215  uint16_t concurrency_ = 1;
216  std::string bindaddr_ = "0.0.0.0";
218 
219  std::tuple<Middlewares...> middlewares_;
220 
221 #ifdef CROW_ENABLE_SSL
222  std::unique_ptr<ssl_server_t> ssl_server_;
223 #endif
224  std::unique_ptr<server_t> server_;
225  };
226  template <typename ... Middlewares>
227  using App = Crow<Middlewares...>;
228  using SimpleApp = Crow<>;
229 }
Crow self_t
Definition: crow.h:35
Definition: http_response.h:12
Definition: utility.h:375
black_magic::arguments< N >::type::template rebind< TaggedRule > & new_rule_tagged(const std::string &rule)
Definition: routing.h:874
Definition: socket_adaptors.h:12
const uint32_t T[512]
Definition: groestl_tables.h:34
T::context & get_context(const request &req)
Definition: crow.h:200
Router router_
Definition: crow.h:217
Definition: http_request.h:23
self_t & concurrency(std::uint16_t concurrency)
Definition: crow.h:84
Definition: routing.h:857
T & get_element_by_type(std::tuple< Args... > &t)
Definition: utility.h:449
Definition: crow.h:32
Crow()
Definition: crow.h:40
void handle_upgrade(const request &req, response &res, Adaptor &&adaptor)
Definition: routing.h:915
std::tuple< Middlewares... > middlewares_
Definition: crow.h:219
void handle(const request &req, response &res)
Definition: routing.h:979
T & get_middleware()
Definition: crow.h:208
void debug_print()
Definition: routing.h:1046
void debug_print()
Definition: crow.h:128
type
Definition: json.h:74
Definition: http_server.h:25
self_t & multithreaded()
Definition: crow.h:79
#define CROW_LOG_DEBUG
Definition: logging.h:139
void * middleware_context
Definition: http_request.h:32
auto route(std::string &&rule) -> typename std::result_of< decltype(&Router::new_rule_tagged< Tag >)(Router, std::string &&)>::type
Definition: crow.h:61
void handle_upgrade(const request &req, response &res, Adaptor &&adaptor)
Definition: crow.h:45
void stop()
Definition: crow.h:114
void validate()
Definition: routing.h:899
void validate()
Definition: crow.h:92
self_t & ssl(T &&)
Definition: crow.h:186
self_t & bindaddr(std::string bindaddr)
Definition: crow.h:73
self_t & ssl_file(T &&, Remain &&...)
Definition: crow.h:175
DynamicRule & route_dynamic(std::string &&rule)
Definition: crow.h:55
self_t & port(std::uint16_t port)
Definition: crow.h:67
std::string bindaddr_
Definition: crow.h:216
Definition: ci_map.h:7
void run()
Definition: crow.h:97
Server< Crow, SocketAdaptor, Middlewares... > server_t
Definition: crow.h:36
uint16_t concurrency_
Definition: crow.h:215
Definition: routing.h:356
void handle(const request &req, response &res)
Definition: crow.h:50
uint16_t port_
Definition: crow.h:214
std::unique_ptr< server_t > server_
Definition: crow.h:224
DynamicRule & new_rule_dynamic(const std::string &rule)
Definition: routing.h:864
json::wvalue context
Definition: mustache.h:12