Crow  1.1
A C++ microframework for the web
app.h
Go to the documentation of this file.
1 /**
2  * \file crow/app.h
3  * \brief This file includes the definition of the crow::Crow class,
4  * the crow::App and crow::SimpleApp aliases, and some macros.
5  *
6  * In this file are defined:
7  * - crow::Crow
8  * - crow::App
9  * - crow::SimpleApp
10  * - \ref CROW_ROUTE
11  * - \ref CROW_BP_ROUTE
12  * - \ref CROW_WEBSOCKET_ROUTE
13  * - \ref CROW_MIDDLEWARES
14  * - \ref CROW_CATCHALL_ROUTE
15  * - \ref CROW_BP_CATCHALL_ROUTE
16  */
17 
18 #pragma once
19 
20 #include <chrono>
21 #include <string>
22 #include <functional>
23 #include <memory>
24 #include <future>
25 #include <cstdint>
26 #include <type_traits>
27 #include <thread>
28 #include <condition_variable>
29 
30 #include "crow/version.h"
31 #include "crow/settings.h"
32 #include "crow/logging.h"
33 #include "crow/utility.h"
34 #include "crow/routing.h"
35 #include "crow/middleware_context.h"
36 #include "crow/http_request.h"
37 #include "crow/http_server.h"
38 #include "crow/task_timer.h"
39 #include "crow/websocket.h"
40 #ifdef CROW_ENABLE_COMPRESSION
41 #include "crow/compression.h"
42 #endif // #ifdef CROW_ENABLE_COMPRESSION
43 
44 
45 #ifdef CROW_MSVC_WORKAROUND
46 
47 #define CROW_ROUTE(app, url) app.route_dynamic(url) // See the documentation in the comment below.
48 #define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_dynamic(url) // See the documentation in the comment below.
49 
50 #else // #ifdef CROW_MSVC_WORKAROUND
51 
52 /**
53  * \def CROW_ROUTE(app, url)
54  * \brief Creates a route for app using a rule.
55  *
56  * It use crow::Crow::route_dynamic or crow::Crow::route to define
57  * a rule for your application. It's usage is like this:
58  *
59  * ```cpp
60  * auto app = crow::SimpleApp(); // or crow::App()
61  * CROW_ROUTE(app, "/")
62  * ([](){
63  * return "<h1>Hello, world!</h1>";
64  * });
65  * ```
66  *
67  * This is the recommended way to define routes in a crow application.
68  * \see [Page of guide "Routes"](https://crowcpp.org/master/guides/routes/).
69  */
70 #define CROW_ROUTE(app, url) app.template route<crow::black_magic::get_parameter_tag(url)>(url)
71 
72 /**
73  * \def CROW_BP_ROUTE(blueprint, url)
74  * \brief Creates a route for a blueprint using a rule.
75  *
76  * It may use crow::Blueprint::new_rule_dynamic or
77  * crow::Blueprint::new_rule_tagged to define a new rule for
78  * an given blueprint. It's usage is similar
79  * to CROW_ROUTE macro:
80  *
81  * ```cpp
82  * crow::Blueprint my_bp();
83  * CROW_BP_ROUTE(my_bp, "/")
84  * ([](){
85  * return "<h1>Hello, world!</h1>";
86  * });
87  * ```
88  *
89  * This is the recommended way to define routes in a crow blueprint
90  * because of its compile-time capabilities.
91  *
92  * \see [Page of the guide "Blueprints"](https://crowcpp.org/master/guides/blueprints/).
93  */
94 #define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_tagged<crow::black_magic::get_parameter_tag(url)>(url)
95 
96 /**
97  * \def CROW_WEBSOCKET_ROUTE(app, url)
98  * \brief Defines WebSocket route for app.
99  *
100  * It binds a WebSocket route to app. Easy solution to implement
101  * WebSockets in your app. The usage syntax of this macro is
102  * like this:
103  *
104  * ```cpp
105  * auto app = crow::SimpleApp(); // or crow::App()
106  * CROW_WEBSOCKET_ROUTE(app, "/ws")
107  * .onopen([&](crow::websocket::connection& conn){
108  * do_something();
109  * })
110  * .onclose([&](crow::websocket::connection& conn, const std::string& reason, uint16_t){
111  * do_something();
112  * })
113  * .onmessage([&](crow::websocket::connection&, const std::string& data, bool is_binary){
114  * if (is_binary)
115  * do_something(data);
116  * else
117  * do_something_else(data);
118  * });
119  * ```
120  *
121  * \see [Page of the guide "WebSockets"](https://crowcpp.org/master/guides/websockets/).
122  */
123 #define CROW_WEBSOCKET_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url).websocket<std::remove_reference<decltype(app)>::type>(&app)
124 
125 /**
126  * \def CROW_MIDDLEWARES(app, ...)
127  * \brief Enable a Middleware for an specific route in app
128  * or blueprint.
129  *
130  * It defines the usage of a Middleware in one route. And it
131  * can be used in both crow::SimpleApp (and crow::App) instances and
132  * crow::Blueprint. Its usage syntax is like this:
133  *
134  * ```cpp
135  * auto app = crow::SimpleApp(); // or crow::App()
136  * CROW_ROUTE(app, "/with_middleware")
137  * .CROW_MIDDLEWARES(app, LocalMiddleware) // Can be used more than one
138  * ([]() { // middleware.
139  * return "Hello world!";
140  * });
141  * ```
142  *
143  * \see [Page of the guide "Middlewares"](https://crowcpp.org/master/guides/middleware/).
144  */
145 #define CROW_MIDDLEWARES(app, ...) template middlewares<typename std::remove_reference<decltype(app)>::type, __VA_ARGS__>()
146 
147 #endif // #ifdef CROW_MSVC_WORKAROUND
148 
149 /**
150  * \def CROW_CATCHALL_ROUTE(app)
151  * \brief Defines a custom catchall route for app using a
152  * custom rule.
153  *
154  * It defines a handler when the client make a request for an
155  * undefined route. Instead of just reply with a `404` status
156  * code (default behavior), you can define a custom handler
157  * using this macro.
158  *
159  * \see [Page of the guide "Routes" (Catchall routes)](https://crowcpp.org/master/guides/routes/#catchall-routes).
160  */
161 #define CROW_CATCHALL_ROUTE(app) app.catchall_route()
162 
163 /**
164  * \def CROW_BP_CATCHALL_ROUTE(blueprint)
165  * \brief Defines a custom catchall route for blueprint
166  * using a custom rule.
167  *
168  * It defines a handler when the client make a request for an
169  * undefined route in the blueprint.
170  *
171  * \see [Page of the guide "Blueprint" (Define a custom Catchall route)](https://crowcpp.org/master/guides/blueprints/#define-a-custom-catchall-route).
172  */
173 #define CROW_BP_CATCHALL_ROUTE(blueprint) blueprint.catchall_rule()
174 
175 
176 /**
177  * \namespace crow
178  * \brief The main namespace of the library. In this namespace
179  * is defined the most important classes and functions of the
180  * library.
181  *
182  * Within this namespace, the Crow class, Router class, Connection
183  * class, and other are defined.
184  */
185 namespace crow
186 {
187 #ifdef CROW_ENABLE_SSL
188  using ssl_context_t = asio::ssl::context;
189 #endif
190  /**
191  * \class Crow
192  * \brief The main server application class.
193  *
194  * Use crow::SimpleApp or crow::App<Middleware1, Middleware2, etc...> instead of
195  * directly instantiate this class.
196  */
197  template<typename... Middlewares>
198  class Crow
199  {
200  public:
201  /// \brief This is the crow application
202  using self_t = Crow;
203 
204  /// \brief The HTTP server
205  using server_t = Server<Crow, SocketAdaptor, Middlewares...>;
206 
207 #ifdef CROW_ENABLE_SSL
208  /// \brief An HTTP server that runs on SSL with an SSLAdaptor
209  using ssl_server_t = Server<Crow, SSLAdaptor, Middlewares...>;
210 #endif
211  Crow()
212  {}
213 
214  /// \brief Construct Crow with a subset of middleware
215  template<typename... Ts>
216  Crow(Ts&&... ts):
217  middlewares_(make_middleware_tuple(std::forward<Ts>(ts)...))
218  {}
219 
220  /// \brief Process an Upgrade request
221  ///
222  /// Currently used to upgrade an HTTP connection to a WebSocket connection
223  template<typename Adaptor>
224  void handle_upgrade(const request& req, response& res, Adaptor&& adaptor)
225  {
226  router_.handle_upgrade(req, res, adaptor);
227  }
228 
229  /// \brief Process only the method and URL of a request and provide a route (or an error response)
230  std::unique_ptr<routing_handle_result> handle_initial(request& req, response& res)
231  {
232  return router_.handle_initial(req, res);
233  }
234 
235  /// \brief Process the fully parsed request and generate a response for it
236  void handle(request& req, response& res, std::unique_ptr<routing_handle_result>& found)
237  {
238  router_.handle<self_t>(req, res, *found);
239  }
240 
241  /// \brief Process a fully parsed request from start to finish (primarily used for debugging)
242  void handle_full(request& req, response& res)
243  {
244  auto found = handle_initial(req, res);
245  if (found->rule_index)
246  handle(req, res, found);
247  }
248 
249  /// \brief Create a dynamic route using a rule (**Use CROW_ROUTE instead**)
250  DynamicRule& route_dynamic(const std::string& rule)
251  {
252  return router_.new_rule_dynamic(rule);
253  }
254 
255  /// \brief Create a route using a rule (**Use CROW_ROUTE instead**)
256  template<uint64_t Tag>
257 #ifdef CROW_GCC83_WORKAROUND
258  auto& route(const std::string& rule)
259 #else
260  auto route(const std::string& rule)
261 #endif
262 #if defined CROW_CAN_USE_CPP17 && !defined CROW_GCC83_WORKAROUND
263  -> typename std::invoke_result<decltype(&Router::new_rule_tagged<Tag>), Router, const std::string&>::type
264 #elif !defined CROW_GCC83_WORKAROUND
265  -> typename std::result_of<decltype (&Router::new_rule_tagged<Tag>)(Router, const std::string&)>::type
266 #endif
267  {
268  return router_.new_rule_tagged<Tag>(rule);
269  }
270 
271  /// \brief Create a route for any requests without a proper route (**Use CROW_CATCHALL_ROUTE instead**)
273  {
274  return router_.catchall_rule();
275  }
276 
277  /// \brief Set the default max payload size for websockets
278  self_t& websocket_max_payload(uint64_t max_payload)
279  {
280  max_payload_ = max_payload;
281  return *this;
282  }
283 
284  /// \brief Get the default max payload size for websockets
286  {
287  return max_payload_;
288  }
289 
290  self_t& signal_clear()
291  {
292  signals_.clear();
293  return *this;
294  }
295 
296  self_t& signal_add(int signal_number)
297  {
298  signals_.push_back(signal_number);
299  return *this;
300  }
301 
302  std::vector<int> signals()
303  {
304  return signals_;
305  }
306 
307  /// \brief Set the port that Crow will handle requests on
308  self_t& port(std::uint16_t port)
309  {
310  port_ = port;
311  return *this;
312  }
313 
314  /// \brief Get the port that Crow will handle requests on
315  std::uint16_t port() const
316  {
317  if (!server_started_)
318  {
319  return port_;
320  }
321 #ifdef CROW_ENABLE_SSL
322  if (ssl_used_)
323  {
324  return ssl_server_->port();
325  }
326  else
327 #endif
328  {
329  return server_->port();
330  }
331  }
332 
333  /// \brief Set the connection timeout in seconds (default is 5)
334  self_t& timeout(std::uint8_t timeout)
335  {
336  timeout_ = timeout;
337  return *this;
338  }
339 
340  /// \brief Set the server name
342  {
343  server_name_ = server_name;
344  return *this;
345  }
346 
347  /// \brief The IP address that Crow will handle requests on (default is 0.0.0.0)
348  self_t& bindaddr(std::string bindaddr)
349  {
350  bindaddr_ = bindaddr;
351  return *this;
352  }
353 
354  /// \brief Get the address that Crow will handle requests on
355  std::string bindaddr()
356  {
357  return bindaddr_;
358  }
359 
360  /// \brief Run the server on multiple threads using all available threads
362  {
363  return concurrency(std::thread::hardware_concurrency());
364  }
365 
366  /// \brief Run the server on multiple threads using a specific number
368  {
369  if (concurrency < 2) // Crow can have a minimum of 2 threads running
370  concurrency = 2;
371  concurrency_ = concurrency;
372  return *this;
373  }
374 
375  /// \brief Get the number of threads that server is using
376  std::uint16_t concurrency()
377  {
378  return concurrency_;
379  }
380 
381  /// \brief Set the server's log level
382  ///
383  /// Possible values are:
384  /// - crow::LogLevel::Debug (0)
385  /// - crow::LogLevel::Info (1)
386  /// - crow::LogLevel::Warning (2)
387  /// - crow::LogLevel::Error (3)
388  /// - crow::LogLevel::Critical (4)
389  self_t& loglevel(LogLevel level)
390  {
391  crow::logger::setLogLevel(level);
392  return *this;
393  }
394 
395  /// \brief Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1MiB)
396  ///
397  /// Any streamed response is unaffected by Crow's timer, and therefore won't timeout before a response is fully sent.
398  self_t& stream_threshold(size_t threshold)
399  {
400  res_stream_threshold_ = threshold;
401  return *this;
402  }
403 
404  /// \brief Get the response body size (in bytes) beyond which Crow automatically streams responses
406  {
407  return res_stream_threshold_;
408  }
409 
410 
411  self_t& register_blueprint(Blueprint& blueprint)
412  {
413  router_.register_blueprint(blueprint);
414  return *this;
415  }
416 
417  /// \brief Set the function to call to handle uncaught exceptions generated in routes (Default generates error 500).
418  ///
419  /// The function must have the following signature: void(crow::response&).
420  /// It must set the response passed in argument to the function, which will be sent back to the client.
421  /// See Router::default_exception_handler() for the default implementation.
422  template<typename Func>
424  {
425  router_.exception_handler() = std::forward<Func>(f);
426  return *this;
427  }
428 
429  std::function<void(crow::response&)>& exception_handler()
430  {
431  return router_.exception_handler();
432  }
433 
434  /// \brief Set a custom duration and function to run on every tick
435  template<typename Duration, typename Func>
436  self_t& tick(Duration d, Func f)
437  {
438  tick_interval_ = std::chrono::duration_cast<std::chrono::milliseconds>(d);
439  tick_function_ = f;
440  return *this;
441  }
442 
443 #ifdef CROW_ENABLE_COMPRESSION
444 
445  self_t& use_compression(compression::algorithm algorithm)
446  {
447  comp_algorithm_ = algorithm;
448  compression_used_ = true;
449  return *this;
450  }
451 
452  compression::algorithm compression_algorithm()
453  {
454  return comp_algorithm_;
455  }
456 
457  bool compression_used() const
458  {
459  return compression_used_;
460  }
461 #endif
462 
463  /// \brief Apply blueprints
465  {
466 #if defined(__APPLE__) || defined(__MACH__)
467  if (router_.blueprints().empty()) return;
468 #endif
469 
470  for (Blueprint* bp : router_.blueprints())
471  {
472  if (bp->static_dir().empty()) {
473  CROW_LOG_ERROR << "Blueprint " << bp->prefix() << " and its sub-blueprints ignored due to empty static directory.";
474  continue;
475  }
476  auto static_dir_ = crow::utility::normalize_path(bp->static_dir());
477 
478  bp->new_rule_tagged<crow::black_magic::get_parameter_tag(CROW_STATIC_ENDPOINT)>(CROW_STATIC_ENDPOINT)([static_dir_](crow::response& res, std::string file_path_partial) {
479  utility::sanitize_filename(file_path_partial);
480  res.set_static_file_info_unsafe(static_dir_ + file_path_partial);
481  res.end();
482  });
483  }
484 
485  router_.validate_bp();
486  }
487 
488  /// \brief Go through the rules, upgrade them if possible, and add them to the list of rules
490  {
491  if (are_static_routes_added()) return;
492  auto static_dir_ = crow::utility::normalize_path(CROW_STATIC_DIRECTORY);
493 
494  route<crow::black_magic::get_parameter_tag(CROW_STATIC_ENDPOINT)>(CROW_STATIC_ENDPOINT)([static_dir_](crow::response& res, std::string file_path_partial) {
495  utility::sanitize_filename(file_path_partial);
496  res.set_static_file_info_unsafe(static_dir_ + file_path_partial);
497  res.end();
498  });
499  set_static_routes_added();
500  }
501 
502  /// \brief A wrapper for `validate()` in the router
503  void validate()
504  {
505  router_.validate();
506  }
507 
508  /// \brief Run the server
509  void run()
510  {
511 #ifndef CROW_DISABLE_STATIC_DIR
512  add_blueprint();
513  add_static_dir();
514 #endif
515  validate();
516 
517 #ifdef CROW_ENABLE_SSL
518  if (ssl_used_)
519  {
520  router_.using_ssl = true;
521  ssl_server_ = std::move(std::unique_ptr<ssl_server_t>(new ssl_server_t(this, bindaddr_, port_, server_name_, &middlewares_, concurrency_, timeout_, &ssl_context_)));
522  ssl_server_->set_tick_function(tick_interval_, tick_function_);
523  ssl_server_->signal_clear();
524  for (auto snum : signals_)
525  {
526  ssl_server_->signal_add(snum);
527  }
528  notify_server_start();
529  ssl_server_->run();
530  }
531  else
532 #endif
533  {
534  server_ = std::move(std::unique_ptr<server_t>(new server_t(this, bindaddr_, port_, server_name_, &middlewares_, concurrency_, timeout_, nullptr)));
535  server_->set_tick_function(tick_interval_, tick_function_);
536  for (auto snum : signals_)
537  {
538  server_->signal_add(snum);
539  }
540  notify_server_start();
541  server_->run();
542  }
543  }
544 
545  /// \brief Non-blocking version of \ref run()
546  ///
547  /// The output from this method needs to be saved into a variable!
548  /// Otherwise the call will be made on the same thread.
549  std::future<void> run_async()
550  {
551  return std::async(std::launch::async, [&] {
552  this->run();
553  });
554  }
555 
556  /// \brief Stop the server
557  void stop()
558  {
559 #ifdef CROW_ENABLE_SSL
560  if (ssl_used_)
561  {
562  if (ssl_server_) { ssl_server_->stop(); }
563  }
564  else
565 #endif
566  {
567  // TODO(EDev): Move these 6 lines to a method in http_server.
568  std::vector<crow::websocket::connection*> websockets_to_close = websockets_;
569  for (auto websocket : websockets_to_close)
570  {
571  CROW_LOG_INFO << "Quitting Websocket: " << websocket;
572  websocket->close("Server Application Terminated");
573  }
574  if (server_) { server_->stop(); }
575  }
576  }
577 
578  void add_websocket(crow::websocket::connection* conn)
579  {
580  websockets_.push_back(conn);
581  }
582 
583  void remove_websocket(crow::websocket::connection* conn)
584  {
585  websockets_.erase(std::remove(websockets_.begin(), websockets_.end(), conn), websockets_.end());
586  }
587 
588  /// \brief Print the routing paths defined for each HTTP method
589  void debug_print()
590  {
591  CROW_LOG_DEBUG << "Routing:";
592  router_.debug_print();
593  }
594 
595 
596 #ifdef CROW_ENABLE_SSL
597 
598  /// \brief Use certificate and key files for SSL
599  self_t& ssl_file(const std::string& crt_filename, const std::string& key_filename)
600  {
601  ssl_used_ = true;
602  ssl_context_.set_verify_mode(asio::ssl::verify_peer);
603  ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
604  ssl_context_.use_certificate_file(crt_filename, ssl_context_t::pem);
605  ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
606  ssl_context_.set_options(
607  asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
608  return *this;
609  }
610 
611  /// \brief Use `.pem` file for SSL
612  self_t& ssl_file(const std::string& pem_filename)
613  {
614  ssl_used_ = true;
615  ssl_context_.set_verify_mode(asio::ssl::verify_peer);
616  ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
617  ssl_context_.load_verify_file(pem_filename);
618  ssl_context_.set_options(
619  asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
620  return *this;
621  }
622 
623  /// \brief Use certificate chain and key files for SSL
624  self_t& ssl_chainfile(const std::string& crt_filename, const std::string& key_filename)
625  {
626  ssl_used_ = true;
627  ssl_context_.set_verify_mode(asio::ssl::verify_peer);
628  ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
629  ssl_context_.use_certificate_chain_file(crt_filename);
630  ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
631  ssl_context_.set_options(
632  asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
633  return *this;
634  }
635 
636  self_t& ssl(asio::ssl::context&& ctx)
637  {
638  ssl_used_ = true;
639  ssl_context_ = std::move(ctx);
640  return *this;
641  }
642 
643  bool ssl_used() const
644  {
645  return ssl_used_;
646  }
647 #else
648 
649  template<typename T, typename... Remain>
650  self_t& ssl_file(T&&, Remain&&...)
651  {
652  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
653  static_assert(
654  // make static_assert dependent to T; always false
655  std::is_base_of<T, void>::value,
656  "Define CROW_ENABLE_SSL to enable ssl support.");
657  return *this;
658  }
659 
660  template<typename T, typename... Remain>
661  self_t& ssl_chainfile(T&&, Remain&&...)
662  {
663  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
664  static_assert(
665  // make static_assert dependent to T; always false
666  std::is_base_of<T, void>::value,
667  "Define CROW_ENABLE_SSL to enable ssl support.");
668  return *this;
669  }
670 
671  template<typename T>
672  self_t& ssl(T&&)
673  {
674  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
675  static_assert(
676  // make static_assert dependent to T; always false
677  std::is_base_of<T, void>::value,
678  "Define CROW_ENABLE_SSL to enable ssl support.");
679  return *this;
680  }
681 
682  bool ssl_used() const
683  {
684  return false;
685  }
686 #endif
687 
688  // middleware
689  using context_t = detail::context<Middlewares...>;
690  using mw_container_t = std::tuple<Middlewares...>;
691  template<typename T>
692  typename T::context& get_context(const request& req)
693  {
694  static_assert(black_magic::contains<T, Middlewares...>::value, "App doesn't have the specified middleware type.");
695  auto& ctx = *reinterpret_cast<context_t*>(req.middleware_context);
696  return ctx.template get<T>();
697  }
698 
699  template<typename T>
700  T& get_middleware()
701  {
702  return utility::get_element_by_type<T, Middlewares...>(middlewares_);
703  }
704 
705  /// \brief Wait until the server has properly started
707  {
708  {
709  std::unique_lock<std::mutex> lock(start_mutex_);
710  while (!server_started_)
711  cv_started_.wait(lock);
712  }
713  if (server_)
714  server_->wait_for_start();
715 #ifdef CROW_ENABLE_SSL
716  else if (ssl_server_)
717  ssl_server_->wait_for_start();
718 #endif
719  }
720 
721  private:
722  template<typename... Ts>
723  std::tuple<Middlewares...> make_middleware_tuple(Ts&&... ts)
724  {
725  auto fwd = std::forward_as_tuple((ts)...);
726  return std::make_tuple(
727  std::forward<Middlewares>(
728  black_magic::tuple_extract<Middlewares, decltype(fwd)>(fwd))...);
729  }
730 
731  /// \brief Notify anything using \ref wait_for_server_start() to proceed
732  void notify_server_start()
733  {
734  std::unique_lock<std::mutex> lock(start_mutex_);
735  server_started_ = true;
736  cv_started_.notify_all();
737  }
738 
739  void set_static_routes_added() {
740  static_routes_added_ = true;
741  }
742 
743  bool are_static_routes_added() {
744  return static_routes_added_;
745  }
746 
747  private:
748  std::uint8_t timeout_{5};
749  uint16_t port_ = 80;
750  uint16_t concurrency_ = 2;
751  uint64_t max_payload_{UINT64_MAX};
752  std::string server_name_ = std::string("Crow/") + VERSION;
753  std::string bindaddr_ = "0.0.0.0";
754  size_t res_stream_threshold_ = 1048576;
755  Router router_;
756  bool static_routes_added_{false};
757 
758 #ifdef CROW_ENABLE_COMPRESSION
759  compression::algorithm comp_algorithm_;
760  bool compression_used_{false};
761 #endif
762 
763  std::chrono::milliseconds tick_interval_;
764  std::function<void()> tick_function_;
765 
766  std::tuple<Middlewares...> middlewares_;
767 
768 #ifdef CROW_ENABLE_SSL
769  std::unique_ptr<ssl_server_t> ssl_server_;
770  bool ssl_used_{false};
771  ssl_context_t ssl_context_{asio::ssl::context::sslv23};
772 #endif
773 
774  std::unique_ptr<server_t> server_;
775 
776  std::vector<int> signals_{SIGINT, SIGTERM};
777 
778  bool server_started_{false};
779  std::condition_variable cv_started_;
780  std::mutex start_mutex_;
781  std::vector<crow::websocket::connection*> websockets_;
782  };
783 
784  /// \brief Alias of Crow<Middlewares...>. Useful if you want
785  /// a instance of an Crow application that require Middlewares
786  template<typename... Middlewares>
787  using App = Crow<Middlewares...>;
788 
789  /// \brief Alias of Crow<>. Useful if you want a instance of
790  /// an Crow application that doesn't require of Middlewares
791  using SimpleApp = Crow<>;
792 } // namespace crow
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conce...
Definition: routing.h:1114
Definition: routing.h:345
The main server application class.
Definition: app.h:199
self_t & multithreaded()
Run the server on multiple threads using all available threads.
Definition: app.h:361
void stop()
Stop the server.
Definition: app.h:557
self_t & tick(Duration d, Func f)
Set a custom duration and function to run on every tick.
Definition: app.h:436
DynamicRule & route_dynamic(const std::string &rule)
Create a dynamic route using a rule (Use CROW_ROUTE instead)
Definition: app.h:250
size_t & stream_threshold()
Get the response body size (in bytes) beyond which Crow automatically streams responses.
Definition: app.h:405
void run()
Run the server.
Definition: app.h:509
self_t & websocket_max_payload(uint64_t max_payload)
Set the default max payload size for websockets.
Definition: app.h:278
self_t & port(std::uint16_t port)
Set the port that Crow will handle requests on.
Definition: app.h:308
uint64_t websocket_max_payload()
Get the default max payload size for websockets.
Definition: app.h:285
void add_static_dir()
Go through the rules, upgrade them if possible, and add them to the list of rules.
Definition: app.h:489
self_t & ssl_file(const std::string &pem_filename)
Use .pem file for SSL.
Definition: app.h:612
self_t & concurrency(std::uint16_t concurrency)
Run the server on multiple threads using a specific number.
Definition: app.h:367
self_t & timeout(std::uint8_t timeout)
Set the connection timeout in seconds (default is 5)
Definition: app.h:334
Crow self_t
This is the crow application.
Definition: app.h:202
Server< Crow, SocketAdaptor, Middlewares... > server_t
The HTTP server.
Definition: app.h:205
auto route(const std::string &rule) -> typename std::result_of< decltype(&Router::new_rule_tagged< Tag >)(Router, const std::string &)>::type
Create a route using a rule (Use CROW_ROUTE instead)
Definition: app.h:260
void wait_for_server_start()
Wait until the server has properly started.
Definition: app.h:706
void handle_upgrade(const request &req, response &res, Adaptor &&adaptor)
Process an Upgrade request.
Definition: app.h:224
self_t & bindaddr(std::string bindaddr)
The IP address that Crow will handle requests on (default is 0.0.0.0)
Definition: app.h:348
std::unique_ptr< routing_handle_result > handle_initial(request &req, response &res)
Process only the method and URL of a request and provide a route (or an error response)
Definition: app.h:230
self_t & loglevel(LogLevel level)
Set the server's log level.
Definition: app.h:389
void debug_print()
Print the routing paths defined for each HTTP method.
Definition: app.h:589
void handle(request &req, response &res, std::unique_ptr< routing_handle_result > &found)
Process the fully parsed request and generate a response for it.
Definition: app.h:236
self_t & exception_handler(Func &&f)
Set the function to call to handle uncaught exceptions generated in routes (Default generates error 5...
Definition: app.h:423
std::string bindaddr()
Get the address that Crow will handle requests on.
Definition: app.h:355
self_t & ssl_file(const std::string &crt_filename, const std::string &key_filename)
Use certificate and key files for SSL.
Definition: app.h:599
std::uint16_t port() const
Get the port that Crow will handle requests on.
Definition: app.h:315
Server< Crow, SSLAdaptor, Middlewares... > ssl_server_t
An HTTP server that runs on SSL with an SSLAdaptor.
Definition: app.h:209
std::future< void > run_async()
Non-blocking version of run()
Definition: app.h:549
CatchallRule & catchall_route()
Create a route for any requests without a proper route (Use CROW_CATCHALL_ROUTE instead)
Definition: app.h:272
void validate()
A wrapper for validate() in the router.
Definition: app.h:503
Crow(Ts &&... ts)
Construct Crow with a subset of middleware.
Definition: app.h:216
std::uint16_t concurrency()
Get the number of threads that server is using.
Definition: app.h:376
void handle_full(request &req, response &res)
Process a fully parsed request from start to finish (primarily used for debugging)
Definition: app.h:242
self_t & ssl_chainfile(const std::string &crt_filename, const std::string &key_filename)
Use certificate chain and key files for SSL.
Definition: app.h:624
self_t & server_name(std::string server_name)
Set the server name.
Definition: app.h:341
self_t & stream_threshold(size_t threshold)
Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1...
Definition: app.h:398
void add_blueprint()
Apply blueprints.
Definition: app.h:464
A rule that can change its parameters during runtime.
Definition: routing.h:585
Handles matching requests to existing rules and upgrade requests.
Definition: routing.h:1268
Definition: http_server.h:43
The main namespace of the library. In this namespace is defined the most important classes and functi...
Definition: socket_adaptors.h:107
A wrapper for the asio::ip::tcp::socket and asio::ssl::stream.
Definition: socket_adaptors.h:39
An HTTP request.
Definition: http_request.h:36
HTTP response.
Definition: http_response.h:34
void end()
Set the response completion flag and call the handler (to send the response).
Definition: http_response.h:237
void set_static_file_info_unsafe(std::string path)
Return a static file as the response body without sanitizing the path (use set_static_file_info inste...
Definition: http_response.h:295
A base class for websocket connection.
Definition: websocket.h:62