RESTinio
settings.hpp
Go to the documentation of this file.
1 /*
2  restinio
3 */
4 
5 /*!
6  HTTP-Server configuration.
7 */
8 
9 #pragma once
10 
11 #include <restinio/asio_include.hpp>
12 
13 #include <restinio/exception.hpp>
14 #include <restinio/request_handler.hpp>
15 #include <restinio/traits.hpp>
16 
17 #include <restinio/incoming_http_msg_limits.hpp>
18 
19 #include <restinio/variant.hpp>
20 
21 #include <chrono>
22 #include <tuple>
23 #include <utility>
24 
25 namespace restinio
26 {
27 
28 namespace details
29 {
30 
31 //! Default instantiation for a specific type.
32 template < typename Object >
33 inline auto
35 {
36  return std::unique_ptr< Object >{};
37 }
38 
39 template < typename Object >
40 inline auto
42 {
43  return std::make_unique< Object >();
44 }
45 
46 //! Default instantiation for a specific type.
47 template < typename Object >
48 inline auto
50 {
51  return std::shared_ptr< Object >{};
52 }
53 
54 template < typename Object >
55 inline auto
57 {
58  return std::make_shared< Object >();
59 }
60 
61 } /* namespace details */
62 
63 //
64 // create_default_unique_object_instance
65 //
66 
67 //! Default instantiation for a specific type.
68 template < typename Object>
69 inline auto
71 {
72  typename std::is_default_constructible< Object >::type tag;
73  return details::create_default_unique_object_instance< Object >( tag );
74 }
75 
76 //! Default instantiation for default_request_handler_t.
77 template <>
78 inline auto
80 {
82  std::false_type{} );
83 }
84 
85 //
86 // create_default_shared_object_instance
87 //
88 
89 //! Default instantiation for a specific type.
90 template < typename Object>
91 inline auto
93 {
96 }
97 
98 //! Default instantiation for default_request_handler_t.
99 template <>
100 inline auto
102 {
104  std::false_type{} );
105 }
106 
107 //
108 // ensure_created()
109 //
110 
111 //! Ensure that object was created.
112 template < typename Object >
113 auto
117 {
118  if( !mb_created_one )
120 
121  if( !mb_created_one )
122  throw exception_t{ fail_description };
123 
124  return mb_created_one;
125 }
126 
127 //
128 // unsure_created()
129 //
130 
131 //! Ensure that object was created.
132 template < typename Object >
133 auto
137 {
138  if( !mb_created_one )
140 
141  if( !mb_created_one )
142  throw exception_t{ fail_description };
143 
144  return mb_created_one;
145 }
146 
147 
148 //
149 // socket_type_dependent_settings_t
150 //
151 
152 //! Extra settings needed for working with socket.
153 template < typename Settings, typename Socket >
155 {
156 protected :
157  ~socket_type_dependent_settings_t() noexcept = default;
158 
159 public :
160  socket_type_dependent_settings_t() noexcept = default;
161 
164 
166  operator=(const socket_type_dependent_settings_t &) noexcept = default;
167 
169  operator=(socket_type_dependent_settings_t &&) noexcept = delete;
170 
171  // No extra settings by default.
172 };
173 
174 //
175 // acceptor_options_t
176 //
177 
178 //! An adapter for setting acceptor options before running server.
179 /*!
180  Class hides an acceptor object and opens only set/get options API.
181  It is used as an argument for a user defined function-object
182  that can set custom options for acceptor.
183 */
185 {
186  public:
187  acceptor_options_t( asio_ns::ip::tcp::acceptor & acceptor )
188  : m_acceptor{ acceptor }
189  {}
190 
191  //! API for setting/getting options.
192  //! \{
193  template< typename Option >
194  void
195  set_option( const Option & option )
196  {
198  }
199 
200  template< typename Option >
201  void
202  set_option( const Option & option, asio_ns::error_code & ec )
203  {
205  }
206 
207  template< typename Option >
208  void
209  get_option( Option & option )
210  {
212  }
213 
214  template< typename Option >
215  void
216  get_option( Option & option, asio_ns::error_code & ec )
217  {
219  }
220  //! \}
221 
222  private:
224 };
225 
227 
228 template <>
229 inline auto
231 {
233  []( acceptor_options_t & options ){
235  } );
236 }
237 
238 //
239 // socket_options_t
240 //
241 
242 //! An adapter for setting acceptor options before running server.
243 /*!
244  Class hides a socket object and opens only set/get options API.
245  It is used as an argument for a user defined function-object
246  that can set custom options for socket.
247 */
249 {
250  public:
252  //! A reference on the most base class with interface of setting options.
254  : m_socket{ socket }
255  {}
256 
257  //! API for setting/getting options.
258  //! \{
259  template< typename Option >
260  void
262  {
264  }
265 
266  template< typename Option >
267  void
269  {
271  }
272 
273  template< typename Option >
274  void
276  {
278  }
279 
280  template< typename Option >
281  void
283  {
285  }
286  //! \}
287 
288  private:
289  //! A reference on the most base class with interface of setting options.
291 };
292 
294 
295 template <>
296 inline auto
298 {
299  return std::make_unique< socket_options_setter_t >( []( auto & ){} );
300 }
301 
302 //
303 // cleanup_functor_t
304 //
305 /*!
306  * \brief Type of holder for user's cleanup function.
307  */
308 using cleanup_functor_t = std::function< void(void) >;
309 
310 //
311 // connection_state_listener_holder_t
312 //
313 /*!
314  * @brief A special class for holding actual connection state listener.
315  *
316  * This class holds shared pointer to actual connection state listener
317  * and provides an actual implementation of
318  * check_valid_connection_state_listener_pointer() method.
319  *
320  * @since v.0.5.1
321  */
322 template< typename Listener >
324 {
326 
327  static constexpr bool has_actual_connection_state_listener = true;
328 
329  //! Checks that pointer to state listener is not null.
330  /*!
331  * Throws an exception if m_connection_state_listener is nullptr.
332  */
333  void
335  {
337  throw exception_t{ "connection state listener is not specified" };
338  }
339 };
340 
341 /*!
342  * @brief A special class for case when no-op state listener is used.
343  *
344  * Doesn't hold anything and contains empty
345  * check_valid_connection_state_listener_pointer() method.
346  *
347  * @since v.0.5.1
348  */
349 template<>
351 {
352  static constexpr bool has_actual_connection_state_listener = false;
353 
354  void
356  {
357  // Nothing to do.
358  }
359 };
360 
361 //
362 // ip_blocker_holder_t
363 //
364 /*!
365  * @brief A special class for holding actual IP-blocker object.
366  *
367  * This class holds shared pointer to actual IP-blocker
368  * and provides an actual implementation of
369  * check_valid_ip_blocker_pointer() method.
370  *
371  * @since v.0.5.1
372  */
373 template< typename Ip_Blocker >
375 {
376  static_assert(
377  noexcept( std::declval<Ip_Blocker>().inspect(
379  "Ip_Blocker::inspect() method should be noexcept" );
380 
381  static_assert(
382  std::is_same<
384  decltype(std::declval<Ip_Blocker>().inspect(
386  "Ip_Blocker::inspect() should return "
387  "restinio::ip_blocker::inspection_result_t" );
388 
390 
391  static constexpr bool has_actual_ip_blocker = true;
392 
393  //! Checks that pointer to IP-blocker is not null.
394  /*!
395  * Throws an exception if m_ip_blocker is nullptr.
396  */
397  void
399  {
400  if( !m_ip_blocker )
401  throw exception_t{ "IP-blocker is not specified" };
402  }
403 };
404 
405 /*!
406  * @brief A special class for case when no-op IP-blocker is used.
407  *
408  * Doesn't hold anything and contains empty
409  * check_valid_ip_blocker_pointer() method.
410  *
411  * @since v.0.5.1
412  */
413 template<>
415 {
416  static constexpr bool has_actual_ip_blocker = false;
417 
418  void
420  {
421  // Nothing to do.
422  }
423 };
424 
425 //
426 // acceptor_post_bind_hook_t
427 //
428 /*!
429  * @brief A type of callback to be called after a successful invocation
430  * of bind() function for the acceptor.
431  *
432  * @since v.0.6.11
433  */
435  void(asio_ns::ip::tcp::acceptor &) >;
436 
437 namespace details
438 {
439 
440 //
441 // no_address_specified_t
442 //
443 /*!
444  * @brief A special indicator for the case when IP address for a server
445  * is not set explicitly.
446  *
447  * @since v.0.6.11
448  */
450 
451 //
452 // address_variant_t
453 //
454 /*!
455  * @brief A type of variant for holding IP address for a server in
456  * various representations.
457  *
458  * @since v.0.6.11
459  */
462  std::string,
464 
465 //
466 // max_parallel_connections_holder_t
467 //
468 /*!
469  * @brief A special type for holding the value of maximum allowed
470  * count of parallel connections.
471  *
472  * This type is intended to be used as a mixin for
473  * server_settings_t type.
474  *
475  * Holds the value and provides the actual implementations for
476  * getter and setter of that value.
477  *
478  * @since v.0.6.12
479  */
480 template< typename Count_Limiter >
482 {
483  static constexpr bool has_actual_max_parallel_connections = true;
484 
485  /*!
486  * @brief Actual value of the limit.
487  *
488  * By the default the count of parallel connection is not limited.
489  */
492  };
493 
494  std::size_t
495  max_parallel_connections() const noexcept
496  {
498  }
499 
500  void
501  set_max_parallel_connections( std::size_t v ) noexcept
502  {
504  }
505 };
506 
507 /*!
508  * @brief A specialization of max_parallel_connections_holder for the case
509  * when connection count isn't limited.
510  *
511  * Doesn't hold anything. Hasn't a setter.
512  *
513  * The getter returns a value that means that there is no connection
514  * count limit at all.
515  *
516  * @since v.0.6.12
517  */
518 template<>
521 {
522  static constexpr bool has_actual_max_parallel_connections = false;
523 
524  std::size_t
525  max_parallel_connections() const noexcept
526  {
527  return std::numeric_limits<std::size_t>::max();
528  }
529 };
530 
531 } /* namespace details */
532 
533 //
534 // basic_server_settings_t
535 //
536 
537 //! Basic container for http_server settings.
538 /*!
539  * It exists to provide ablity to create various derived classes
540  * like server_settings_t, run_on_this_thread_settings_t,
541  * run_on_this_thread_settings_t and so on.
542  *
543  * \tparam Derived A drived type. Reference to this derived type
544  * will be returned by setters.
545  *
546  * \tparam Traits A type with traits for http_server.
547  */
548 template<typename Derived, typename Traits>
552  typename Traits::connection_state_listener_t >
553  , protected ip_blocker_holder_t< typename Traits::ip_blocker_t >
556 {
559 
563 
565  typename Traits::connection_state_listener_t
566  >::has_actual_connection_state_listener;
567 
568  using ip_blocker_holder_t<
569  typename Traits::ip_blocker_t
570  >::has_actual_ip_blocker;
571 
573 
574  public:
576  std::uint16_t port = 8080,
577  asio_ns::ip::tcp protocol = asio_ns::ip::tcp::v4() )
578  : base_type_t{}
579  , m_port{ port }
580  , m_protocol{ protocol }
581  {}
582 
583  //! Server endpoint.
584  //! \{
585  Derived &
586  port( std::uint16_t p ) &
587  {
588  m_port = p;
589  return reference_to_derived();
590  }
591 
592  Derived &&
593  port( std::uint16_t p ) &&
594  {
595  return std::move( this->port( p ) );
596  }
597 
599  std::uint16_t
600  port() const
601  {
602  return m_port;
603  }
604 
605  Derived &
607  {
608  m_protocol = p;
609  return reference_to_derived();
610  }
611 
612  Derived &&
614  {
615  return std::move( this->protocol( p ) );
616  }
617 
619  asio_ns::ip::tcp
620  protocol() const
621  {
622  return m_protocol;
623  }
624 
625  /*!
626  * Sets the IP address for a server in textual form.
627  *
628  * Usage example:
629  * @code
630  * using my_server_t = restinio::http_server_t< my_server_traits_t >;
631  * my_server_t server{
632  * restinio::own_io_context(),
633  * [](auto & settings) {
634  * settings.port(8080);
635  * settings.address("192.168.1.1");
636  * settings.request_handler(...);
637  * ...
638  * }
639  * };
640  * @endcode
641  */
642  Derived &
644  {
645  m_address = std::move(addr);
646  return reference_to_derived();
647  }
648 
649  /*!
650  * Sets the IP address for a server in textual form.
651  *
652  * Usage example:
653  * @code
654  * restinio::run(
655  * restinio::on_this_thread()
656  * .port(...)
657  * .address("192.168.1.1")
658  * .request_handler(...)
659  * );
660  * @endcode
661  */
662  Derived &&
664  {
665  return std::move( this->address( std::move( addr ) ) );
666  }
667 
668  /*!
669  * Sets the IP address for a server in binary form.
670  *
671  * Usage example:
672  * @code
673  * auto actual_ip = asio::ip::address::from_string(app.config().ip_addr());
674  * ...
675  * using my_server_t = restinio::http_server_t< my_server_traits_t >;
676  * my_server_t server{
677  * restinio::own_io_context(),
678  * [actual_ip](auto & settings) {
679  * settings.port(8080);
680  * settings.address(actual_ip);
681  * settings.request_handler(...);
682  * ...
683  * }
684  * };
685  * @endcode
686  */
687  Derived &
689  {
690  m_address = addr;
691  return reference_to_derived();
692  }
693 
694  /*!
695  * Sets the IP address for a server in binary form.
696  *
697  * Usage example:
698  * @code
699  * auto actual_ip = asio::ip::address::from_string(app.config().ip_addr());
700  * ...
701  * restinio::run(
702  * restinio::on_this_thread()
703  * .port(...)
704  * .address(actual_ip)
705  * .request_handler(...)
706  * );
707  * @endcode
708  */
709  Derived &&
711  {
712  return std::move( this->address( addr ) );
713  }
714 
716  const details::address_variant_t &
717  address() const
718  {
719  return m_address;
720  }
721  //! \}
722 
723  //! Size of buffer for io operations.
724  /*!
725  It limits a size of chunk that can be read from socket in a single
726  read operattion (async read).
727  */
728  //! {
729  Derived &
731  {
732  m_buffer_size = s;
733  return reference_to_derived();
734  }
735 
736  Derived &&
738  {
739  return std::move( this->buffer_size( s ) );
740  }
741 
742  std::size_t
743  buffer_size() const
744  {
745  return m_buffer_size;
746  }
747  //! }
748 
749  //! A period for holding connection before completely receiving
750  //! new http-request. Starts counting since connection is establised
751  //! or a previous request was responsed.
752  /*!
753  Generaly it defines timeout for keep-alive connections.
754  */
755  //! \{
756  Derived &
758  {
760  return reference_to_derived();
761  }
762 
763  Derived &&
765  {
766  return std::move( this->read_next_http_message_timelimit( std::move( d ) ) );
767  }
768 
771  {
773  }
774  //! \}
775 
776  //! A period of time wait for response to be written to socket.
777  //! \{
778  Derived &
780  {
782  return reference_to_derived();
783  }
784 
785  Derived &&
787  {
788  return std::move( this->write_http_response_timelimit( std::move( d ) ) );
789  }
790 
793  {
795  }
796  //! \}
797 
798  //! A period of time that is given for a handler to create response.
799  //! \{
800  Derived &
802  {
804  return reference_to_derived();
805  }
806 
807  Derived &&
809  {
810  return std::move( this->handle_request_timeout( std::move( d ) ) );
811  }
812 
815  {
817  }
818  //! \}
819 
820  //! Max pipelined requests able to receive on single connection.
821  //! \{
822  Derived &
824  {
826  return reference_to_derived();
827  }
828 
829  Derived &&
831  {
832  return std::move( this->max_pipelined_requests( mpr ) );
833  }
834 
835  std::size_t
837  {
839  }
840  //! \}
841 
842 
843  //! Request handler.
844  //! \{
846 
847  Derived &
848  request_handler( std::unique_ptr< request_handler_t > handler ) &
849  {
851  return reference_to_derived();
852  }
853 
854  template< typename... Params >
855  Derived &
856  request_handler( Params &&... params ) &
857  {
858  return set_unique_instance(
860  std::forward< Params >( params )... );
861  }
862 
863 
864  template< typename... Params >
865  Derived &&
866  request_handler( Params &&... params ) &&
867  {
868  return std::move( this->request_handler( std::forward< Params >( params )... ) );
869  }
870 
873  {
874  return ensure_created(
876  "request handler must be set" );
877  }
878  //! \}
879 
880 
881  //! Timers manager.
882  //! \{
883  using timer_manager_t = typename Traits::timer_manager_t;
884  using timer_factory_t = typename timer_manager_t::factory_t;
885 
886  template< typename... Params >
887  Derived &
888  timer_manager( Params &&... params ) &
889  {
890  return set_unique_instance(
892  std::forward< Params >( params )... );
893  }
894 
895  template< typename... Params >
896  Derived &&
897  timer_manager( Params &&... params ) &&
898  {
899  return std::move( this->timer_manager( std::forward< Params >( params )... ) );
900  }
901 
904  {
905  return ensure_created(
907  "timer manager is not set" );
908  }
909  //! \}
910 
911  //! Logger.
912  //! \{
913  using logger_t = typename Traits::logger_t;
914 
915  template< typename... Params >
916  Derived &
917  logger( Params &&... params ) &
918  {
919  return set_unique_instance(
920  m_logger,
921  std::forward< Params >( params )... );
922  }
923 
924  template< typename... Params >
925  Derived &&
926  logger( Params &&... params ) &&
927  {
928  return std::move( this->logger( std::forward< Params >( params )... ) );
929  }
930 
933  {
934  return ensure_created(
935  std::move( m_logger ),
936  "logger must be set" );
937  }
938  //! \}
939 
940  //! Acceptor options setter.
941  //! \{
942  Derived &
943  acceptor_options_setter( acceptor_options_setter_t aos ) &
944  {
945  if( !aos )
946  throw exception_t{ "acceptor options setter cannot be empty" };
947 
948  return set_unique_instance(
950  std::move( aos ) );
951  }
952 
953  Derived &&
954  acceptor_options_setter( acceptor_options_setter_t aos ) &&
955  {
956  return std::move( this->acceptor_options_setter( std::move( aos ) ) );
957  }
958 
961  {
962  return ensure_created(
964  "acceptor options setter must be set" );
965  }
966  //! \}
967 
968  //! Socket options setter.
969  //! \{
970  Derived &
971  socket_options_setter( socket_options_setter_t sos ) &
972  {
973  if( !sos )
974  throw exception_t{ "socket options setter cannot be empty" };
975 
976  return set_unique_instance(
978  std::move( sos ) );
979  }
980 
981  Derived &&
982  socket_options_setter( socket_options_setter_t sos ) &&
983  {
984  return std::move( this->socket_options_setter( std::move( sos ) ) );
985  }
986 
989  {
990  return ensure_created(
992  "socket options setter must be set" );
993  }
994  //! \}
995 
996  //! Max number of running concurrent accepts.
997  /*!
998  When running server on N threads
999  then up to N accepts can be handled concurrently.
1000  */
1001  //! \{
1002  Derived &
1003  concurrent_accepts_count( std::size_t n ) &
1004  {
1005  if( 0 == n || 1024 < n )
1006  throw exception_t{
1007  fmt::format(
1008  "invalid value for number of cuncurrent connects: {}",
1009  n ) };
1010 
1012  return reference_to_derived();
1013  }
1014 
1015  Derived &&
1016  concurrent_accepts_count( std::size_t n ) &&
1017  {
1018  return std::move( this->concurrent_accepts_count( n ) );
1019  }
1020 
1021  std::size_t
1023  {
1025  }
1026  //! \}
1027 
1028  //! Do separate an accept operation and connection instantiation.
1029  /*!
1030  For the cases when a lot of connection can be fired by clients
1031  in a short time interval, it is vital to accept connections
1032  and initiate new accept operations as quick as possible.
1033  So creating connection instance that involves allocations
1034  and initialization can be done in a context that
1035  is independent to acceptors one.
1036  */
1037  //! \{
1038  Derived &
1039  separate_accept_and_create_connect( bool do_separate ) & noexcept
1040  {
1042  return reference_to_derived();
1043  }
1044 
1045  Derived &&
1046  separate_accept_and_create_connect( bool do_separate ) && noexcept
1047  {
1049  }
1050 
1051  bool
1053  {
1055  }
1056  //! \}
1057 
1058  //! Cleanup function.
1059  //! \{
1060  template< typename Func >
1061  Derived &
1062  cleanup_func( Func && func ) &
1063  {
1065  return reference_to_derived();
1066  }
1067 
1068  template< typename Func >
1069  Derived &&
1070  cleanup_func( Func && func ) &&
1071  {
1072  return std::move(this->cleanup_func( std::forward<Func>(func) ));
1073  }
1074 
1075  /*!
1076  * @note
1077  * This method is intended to be used by RESTinio and it can be
1078  * changed or removed in future versions of RESTinio without any
1079  * notice.
1080  */
1081  RESTINIO_NODISCARD
1082  cleanup_functor_t
1084  {
1085  return std::move(m_cleanup_functor);
1086  }
1087  //! \}
1088 
1089  /*!
1090  * @brief Setter for connection state listener.
1091  *
1092  * @note connection_state_listener() method should be called if
1093  * user specify its type for connection_state_listener_t traits.
1094  * For example:
1095  * @code
1096  * class my_state_listener_t {
1097  * ...
1098  * public:
1099  * ...
1100  * void state_changed(const restinio::connection_state::notice_t & notice) noexcept {
1101  * ...
1102  * }
1103  * };
1104  *
1105  * struct my_traits_t : public restinio::default_traits_t {
1106  * using connection_state_listener_t = my_state_listener_t;
1107  * };
1108  *
1109  * restinio::server_setting_t<my_traits_t> settings;
1110  * setting.connection_state_listener( std::make_shared<my_state_listener_t>(...) );
1111  * ...
1112  * @endcode
1113  *
1114  * @attention This method can't be called if the default no-op
1115  * state listener is used in server traits.
1116  *
1117  * @since v.0.5.1
1118  */
1119  Derived &
1122  {
1123  static_assert(
1125  "connection_state_listener(listener) can't be used "
1126  "for the default connection_state::noop_listener_t" );
1127 
1129  return reference_to_derived();
1130  }
1131 
1132  /*!
1133  * @brief Setter for connection state listener.
1134  *
1135  * @note connection_state_listener() method should be called if
1136  * user specify its type for connection_state_listener_t traits.
1137  * For example:
1138  * @code
1139  * class my_state_listener_t {
1140  * ...
1141  * public:
1142  * ...
1143  * void state_changed(const restinio::connection_state::notice_t & notice) noexcept {
1144  * ...
1145  * }
1146  * };
1147  *
1148  * struct my_traits_t : public restinio::default_traits_t {
1149  * using connection_state_listener_t = my_state_listener_t;
1150  * };
1151  *
1152  * restinio::run( restinio::on_this_thread<my_traits_t>()
1153  * .connection_state_listener( std::make_shared<my_state_listener_t>(...) )
1154  * .port(...)
1155  * ...);
1156  * @endcode
1157  *
1158  * @attention This method can't be called if the default no-op
1159  * state listener is used in server traits.
1160  *
1161  * @since v.0.5.1
1162  */
1163  Derived &&
1166  {
1167  return std::move(this->connection_state_listener(
1168  std::move(listener)));
1169  }
1170 
1171  /*!
1172  * @brief Get reference to connection state listener.
1173  *
1174  * @attention This method can't be called if the default no-op
1175  * state listener is used in server traits.
1176  *
1177  * @since v.0.5.1
1178  */
1179  const std::shared_ptr< typename Traits::connection_state_listener_t > &
1180  connection_state_listener() const noexcept
1181  {
1182  static_assert(
1184  "connection_state_listener() can't be used "
1185  "for the default connection_state::noop_listener_t" );
1186 
1187  return this->m_connection_state_listener;
1188  }
1189 
1190  /*!
1191  * @brief Internal method for checking presence of state listener
1192  * object.
1193  *
1194  * If a user specifies custom state listener type but doesn't
1195  * set a pointer to listener object that method throws an exception.
1196  *
1197  * @since v.0.5.1
1198  */
1199  void
1201  {
1203  }
1204 
1205  /*!
1206  * @brief Setter for IP-blocker.
1207  *
1208  * @note ip_blocker() method should be called if
1209  * user specify its type for ip_blocker_t traits.
1210  * For example:
1211  * @code
1212  * class my_ip_blocker_t {
1213  * ...
1214  * public:
1215  * ...
1216  * restinio::ip_blocker::inspection_result_t
1217  * inspect(const restinio::ip_blocker::incoming_info_t & info) noexcept {
1218  * ...
1219  * }
1220  * };
1221  *
1222  * struct my_traits_t : public restinio::default_traits_t {
1223  * using ip_blocker_t = my_ip_blocker_t;
1224  * };
1225  *
1226  * restinio::server_setting_t<my_traits_t> settings;
1227  * setting.ip_blocker( std::make_shared<my_ip_blocker_t>(...) );
1228  * ...
1229  * @endcode
1230  *
1231  * @attention This method can't be called if the default no-op
1232  * IP-blocker is used in server traits.
1233  *
1234  * @since v.0.5.1
1235  */
1236  Derived &
1238  std::shared_ptr< typename Traits::ip_blocker_t > blocker ) &
1239  {
1240  static_assert(
1242  "ip_blocker(blocker) can't be used "
1243  "for the default ip_blocker::noop_ip_blocker_t" );
1244 
1245  this->m_ip_blocker = std::move(blocker);
1246  return reference_to_derived();
1247  }
1248 
1249  /*!
1250  * @brief Setter for IP-blocker.
1251  *
1252  * @note ip_blocker() method should be called if
1253  * user specify its type for ip_blocker_t traits.
1254  * For example:
1255  * @code
1256  * class my_ip_blocker_t {
1257  * ...
1258  * public:
1259  * ...
1260  * restinio::ip_blocker::inspection_result_t
1261  * inspect(const restinio::ip_blocker::incoming_info_t & info) noexcept {
1262  * ...
1263  * }
1264  * };
1265  *
1266  * struct my_traits_t : public restinio::default_traits_t {
1267  * using ip_blocker_t = my_ip_blocker_t;
1268  * };
1269  *
1270  * restinio::run( restinio::on_this_thread<my_traits_t>()
1271  * .ip_blocker( std::make_shared<my_ip_blocker_t>(...) )
1272  * .port(...)
1273  * ...);
1274  * @endcode
1275  *
1276  * @attention This method can't be called if the default no-op
1277  * state listener is used in server traits.
1278  *
1279  * @since v.0.5.1
1280  */
1281  Derived &&
1283  std::shared_ptr< typename Traits::ip_blocker_t > blocker ) &&
1284  {
1285  return std::move(this->ip_blocker(std::move(blocker)));
1286  }
1287 
1288  /*!
1289  * @brief Get reference to IP-blocker.
1290  *
1291  * @attention This method can't be called if the default no-op
1292  * IP-blocker is used in server traits.
1293  *
1294  * @since v.0.5.1
1295  */
1296  const std::shared_ptr< typename Traits::ip_blocker_t > &
1297  ip_blocker() const noexcept
1298  {
1299  static_assert(
1301  "ip_blocker() can't be used "
1302  "for the default ip_blocker::noop_ip_blocker_t" );
1303 
1304  return this->m_ip_blocker;
1305  }
1306 
1307  /*!
1308  * @brief Internal method for checking presence of IP-blocker object.
1309  *
1310  * If a user specifies custom IP-blocker type but doesn't
1311  * set a pointer to blocker object that method throws an exception.
1312  *
1313  * @since v.0.5.1
1314  */
1315  void
1317  {
1319  }
1320 
1321  // Acceptor post-bind hook.
1322  /*!
1323  * @brief A setter for post-bind callback.
1324  *
1325  * Usage example:
1326  * @code
1327  * using my_server_t = restinio::http_server_t< my_server_traits_t >;
1328  * my_server_t server{
1329  * restinio::own_io_context(),
1330  * [](auto & settings) {
1331  * settings.port(...);
1332  * settings.address(...);
1333  * settings.acceptor_post_bind_hook(
1334  * [](asio::ip::tcp::acceptor & acceptor) {
1335  * ...
1336  * })
1337  * settings.request_handler(...);
1338  * ...
1339  * }
1340  * };
1341  * @endcode
1342  *
1343  * @since v.0.6.11
1344  */
1345  Derived &
1347  {
1348  if( !hook )
1349  throw exception_t{ "acceptor_post_bind_hook cannot be empty" };
1350 
1352  return reference_to_derived();
1353  }
1354 
1355  /*!
1356  * @brief A setter for post-bind callback.
1357  *
1358  * Usage example:
1359  * @code
1360  * restinio::run(
1361  * restinio::on_this_thread()
1362  * .port(...)
1363  * .address(...)
1364  * .acceptor_post_bind_hook(
1365  * [](asio::ip::tcp::acceptor & acceptor) {
1366  * ...
1367  * })
1368  * .request_handler(...)
1369  * );
1370  * @endcode
1371  *
1372  * @since v.0.6.11
1373  */
1374  Derived &&
1376  {
1377  return std::move(this->acceptor_post_bind_hook( std::move(hook) ));
1378  }
1379 
1380  /*!
1381  * @brief A getter for post-bind callback.
1382  *
1383  * @note
1384  * This method is intended to be used by RESTinio and it can be
1385  * changed or removed in future versions of RESTinio without any
1386  * notice.
1387  *
1388  * @since v.0.6.11
1389  */
1393  {
1395  }
1396 
1397  /*!
1398  * @brief Getter of optional limits for incoming HTTP messages.
1399  *
1400  * In v.0.6.12 if the limits for incoming HTTP messages are not
1401  * set explicitely then a defaultly constructed instance of
1402  * incoming_http_msg_limits_t is used. This means the absence of
1403  * any limits.
1404  *
1405  * But if the limits were set by using appropriate setters then
1406  * a reference to an instance with user-defined limits is returned.
1407  *
1408  * @since v.0.6.12
1409  */
1412  incoming_http_msg_limits() const noexcept
1413  {
1415  }
1416 
1417  /*!
1418  * @brief Setter of optional limits for incoming HTTP messages.
1419  *
1420  * Usage example:
1421  * @code
1422  * struct my_traits : public restinio::default_traits_t { ... };
1423  * restinio::server_settings_t<my_traits> settings;
1424  * settings.incoming_http_msg_limits(
1425  * restinio::incoming_http_msg_limits_t{}
1426  * .max_url_size(8000u)
1427  * .max_field_name_size(2048u)
1428  * .max_field_value_size(4096u)
1429  * );
1430  * ...
1431  * auto server = restinio::run_async(
1432  * restinio::own_io_context(),
1433  * std::move(settings),
1434  * std::thread::hardware_concurrency());
1435  * @endcode
1436  *
1437  * @since v.0.6.12
1438  */
1439  Derived &
1441  const incoming_http_msg_limits_t & limits ) & noexcept
1442  {
1444  return reference_to_derived();
1445  }
1446 
1447  /*!
1448  * @brief Setter of optional limits for incoming HTTP messages.
1449  *
1450  * Usage example:
1451  * @code
1452  * struct my_traits : public restinio::default_traits_t { ... };
1453  * ...
1454  * auto server = restinio::run_async(
1455  * restinio::own_io_context(),
1456  * restinio::server_settings_t<my_traits>{}
1457  * ...
1458  * .incoming_http_msg_limits(
1459  * restinio::incoming_http_msg_limits_t{}
1460  * .max_url_size(8000u)
1461  * .max_field_name_size(2048u)
1462  * .max_field_value_size(4096u)
1463  * ),
1464  * std::thread::hardware_concurrency());
1465  * @endcode
1466  *
1467  * @since v.0.6.12
1468  */
1469  Derived &&
1471  const incoming_http_msg_limits_t & limits ) && noexcept
1472  {
1473  return std::move(this->incoming_http_msg_limits(limits));
1474  }
1475 
1476  /*!
1477  * @brief Setter for connection count limit.
1478  *
1479  * @note
1480  * This setter can be called only if the usage of connection
1481  * count limit is turned on explicitly.
1482  *
1483  * Usage example:
1484  * @code
1485  * struct my_traits : public restinio::default_traits_t {
1486  * static constexpr bool use_connection_count_limiter = true;
1487  * };
1488  * ...
1489  * restinio::server_settings_t<my_traits> settings;
1490  * settings.max_parallel_connections( 1000u );
1491  * ...
1492  * auto server = restinio::run_async(
1493  * restinio::own_io_context(),
1494  * std::move(settings),
1495  * std::thread::hardware_concurrency());
1496  * @endcode
1497  *
1498  * @since v.0.6.12
1499  */
1500  Derived &
1502  {
1503  static_assert(
1505  "max_parallel_connections(value) can't be used "
1506  "for the noop_connection_count_limiter_t" );
1507 
1509  return reference_to_derived();
1510  }
1511 
1512  /*!
1513  * @brief Setter for connection count limit.
1514  *
1515  * @note
1516  * This setter can be called only if the usage of connection
1517  * count limit is turned on explicitly.
1518  *
1519  * Usage example:
1520  * @code
1521  * struct my_traits : public restinio::default_traits_t {
1522  * static constexpr bool use_connection_count_limiter = true;
1523  * };
1524  * ...
1525  * auto server = restinio::run_async(
1526  * restinio::own_io_context(),
1527  * restinio::server_settings_t<my_traits>{}
1528  * ...
1529  * .max_parallel_connections(1000u),
1530  * std::thread::hardware_concurrency());
1531  * @endcode
1532  *
1533  * @since v.0.6.12
1534  */
1535  Derived &&
1537  {
1538  return std::move(this->max_parallel_connections( value ));
1539  }
1540 
1542 
1543  /*!
1544  * @name User-data factory.
1545  * @{
1546  */
1547  /*!
1548  * @brief The actual type of extra-data-factory.
1549  * @since v.0.6.13
1550  */
1551  using extra_data_factory_t = typename Traits::extra_data_factory_t;
1552  /*!
1553  * @brief Type of shared-pointer to extra-data-factory.
1554  * @since v.0.6.13
1555  */
1557 
1558  /*!
1559  * @brief Setter for extra-data-factory.
1560  *
1561  * Usage example:
1562  * @code
1563  * class my_extra_data_factory {
1564  * ... // Some factory's data.
1565  * public:
1566  * struct data_t {...};
1567  *
1568  * my_extra_data_factory(...) {...}
1569  *
1570  * void make_within(restinio::extra_data_buffer_t<data_t> buf) {
1571  * new(buf.get()) data_t{...};
1572  * }
1573  * };
1574  *
1575  * struct my_traits : public restinio::default_traits_t {
1576  * using extra_data_factory_t = my_extra_data_factory;
1577  * };
1578  *
1579  * restinio::server_settings_t<my_traits> settings;
1580  * ...
1581  * settings.extra_data_factory(std::make_shared<my_extra_data_factory>(...));
1582  * ...
1583  * auto server = restinio::run_async(
1584  * restinio::own_io_context(),
1585  * std::move(settings),
1586  * std::thread::hardware_concurrency());
1587  * @endcode
1588  *
1589  * @since v.0.6.13
1590  */
1591  Derived &
1593  extra_data_factory_handle_t factory ) &
1594  {
1596  return reference_to_derived();
1597  }
1598 
1599  /*!
1600  * @brief Setter for extra-data-factory.
1601  *
1602  * Usage example:
1603  * @code
1604  * class my_extra_data_factory {
1605  * ... // Some factory's data.
1606  * public:
1607  * struct data_t {...};
1608  *
1609  * my_extra_data_factory(...) {...}
1610  *
1611  * void make_within(restinio::extra_data_buffer_t<data_t> buf) {
1612  * new(buf.get()) data_t{...};
1613  * }
1614  * };
1615  *
1616  * struct my_traits : public restinio::default_traits_t {
1617  * using extra_data_factory_t = my_extra_data_factory;
1618  * };
1619  *
1620  * auto server = restinio::run_async(
1621  * restinio::own_io_context(),
1622  * restinio::server_settings_t<my_traits>{}
1623  * .extra_data_factory(std::make_shared<my_extra_data_factory>(...))
1624  * ...
1625  * ,
1626  * std::thread::hardware_concurrency());
1627  * @endcode
1628  *
1629  * @since v.0.6.13
1630  */
1631  Derived &&
1633  extra_data_factory_handle_t factory ) &&
1634  {
1635  return std::move(this->extra_data_factory( std::move(factory) ));
1636  }
1637 
1638  /*!
1639  * @brief Extractor for extra-data-factory.
1640  * @since v.0.6.13
1641  */
1642  RESTINIO_NODISCARD
1643  extra_data_factory_handle_t
1645  {
1646  return ensure_created(
1647  std::move(this->m_extra_data_factory),
1648  "extra_data_factory is not set" );
1649  }
1650  /*!
1651  * @}
1652  */
1653 
1654  private:
1655  Derived &
1657  {
1658  return static_cast<Derived &>(*this);
1659  }
1660 
1661  template< typename Target, typename... Params >
1662  Derived &
1664  {
1665  t =
1666  std::make_unique< Target >(
1667  std::forward< Params >( params )... );
1668 
1669  return reference_to_derived();
1670  }
1671 
1672  template< typename Target, typename... Params >
1673  Derived &
1675  {
1676  t =
1677  std::make_shared< Target >(
1678  std::forward< Params >( params )... );
1679 
1680  return reference_to_derived();
1681  }
1682 
1683  //! Server endpoint.
1684  //! \{
1687  /*!
1688  * @note
1689  * This member has type address_variant_t since v.0.6.11
1690  */
1692  //! \}
1693 
1694  //! Size of buffer for io operations.
1695  std::size_t m_buffer_size{ 4 * 1024 };
1696 
1697  //! Operations timeouts.
1698  //! \{
1701 
1704 
1707  //! \}
1708 
1709  //! Max pipelined requests to receive on single connection.
1711 
1712  //! Request handler.
1714 
1715  //! Timers factory.
1717 
1718  //! Logger.
1720 
1721  //! Acceptor options setter.
1723 
1724  //! A hook to be called just after a successful call to bind for acceptor.
1725  /*!
1726  * An empty lambda is used by default.
1727  *
1728  * @since v.0.6.11
1729  */
1731  [](asio_ns::ip::tcp::acceptor &) {}
1732  };
1733 
1734  //! Socket options setter.
1736 
1738 
1739  //! Do separate an accept operation and connection instantiation.
1741 
1742  //! Optional cleanup functor.
1744 
1745  /*!
1746  * @brief Limits for incoming HTTP messages.
1747  *
1748  * @since v.0.6.12
1749  */
1751 
1752  /*!
1753  * @brief User-data-factory for server.
1754  *
1755  * @since v.0.6.13
1756  */
1758 };
1759 
1760 //
1761 // server_settings_t
1762 //
1763 
1764 //! A fluent style interface for setting http server params.
1765 template<typename Traits = default_traits_t>
1767  : public basic_server_settings_t< server_settings_t<Traits>, Traits >
1768 {
1769  using base_type_t = basic_server_settings_t<
1770  server_settings_t<Traits>, Traits>;
1771 public:
1772  using base_type_t::base_type_t;
1773 };
1774 
1775 template < typename Traits, typename Configurator >
1776 auto
1777 exec_configurator( Configurator && configurator )
1778 {
1779  server_settings_t< Traits > result;
1780 
1781  configurator( result );
1782 
1783  return result;
1784 }
1785 
1786 } /* namespace restinio */
Derived && separate_accept_and_create_connect(bool do_separate) &&noexcept
Definition: settings.hpp:1046
Derived && extra_data_factory(extra_data_factory_handle_t factory) &&
Setter for extra-data-factory.
Definition: settings.hpp:1632
std::unique_ptr< logger_t > logger()
Definition: settings.hpp:932
Derived && timer_manager(Params &&... params) &&
Definition: settings.hpp:897
static constexpr bool has_actual_ip_blocker
Definition: settings.hpp:391
auto create_default_unique_object_instance(std::true_type)
Definition: settings.hpp:41
std::size_t m_max_parallel_connections
Actual value of the limit.
Definition: settings.hpp:490
std::size_t max_parallel_connections() const noexcept
Definition: settings.hpp:495
void set_max_parallel_connections(std::size_t v) noexcept
Definition: settings.hpp:501
std::size_t concurrent_accepts_count() const
Definition: settings.hpp:1022
std::unique_ptr< logger_t > m_logger
Logger.
Definition: settings.hpp:1719
std::unique_ptr< request_handler_t > m_request_handler
Request handler.
Definition: settings.hpp:1713
void get_option(Option &option, asio_ns::error_code &ec)
Definition: settings.hpp:216
std::unique_ptr< acceptor_options_setter_t > m_acceptor_options_setter
Acceptor options setter.
Definition: settings.hpp:1722
Derived && concurrent_accepts_count(std::size_t n) &&
Definition: settings.hpp:1016
bool separate_accept_and_create_connect() const noexcept
Definition: settings.hpp:1052
void set_option(const Option &option, asio_ns::error_code &ec)
Definition: settings.hpp:202
void check_valid_ip_blocker_pointer() const
Checks that pointer to IP-blocker is not null.
Definition: settings.hpp:398
details::address_variant_t m_address
Definition: settings.hpp:1691
void check_valid_connection_state_listener_pointer() const
Checks that pointer to state listener is not null.
Definition: settings.hpp:334
Derived & request_handler(std::unique_ptr< request_handler_t > handler) &
Definition: settings.hpp:848
A special type for holding the value of maximum allowed count of parallel connections.
Definition: settings.hpp:481
Derived & logger(Params &&... params) &
Definition: settings.hpp:917
Derived & concurrent_accepts_count(std::size_t n) &
Max number of running concurrent accepts.
Definition: settings.hpp:1003
acceptor_options_t(asio_ns::ip::tcp::acceptor &acceptor)
Definition: settings.hpp:187
static constexpr bool has_actual_connection_state_listener
Definition: settings.hpp:327
Derived && cleanup_func(Func &&func) &&
Definition: settings.hpp:1070
std::unique_ptr< request_handler_t > request_handler()
Definition: settings.hpp:872
std::unique_ptr< timer_factory_t > timer_factory()
Definition: settings.hpp:903
auto create_default_unique_object_instance()
Default instantiation for a specific type.
Definition: settings.hpp:70
std::shared_ptr< Ip_Blocker > m_ip_blocker
Definition: settings.hpp:379
Derived && acceptor_options_setter(acceptor_options_setter_t aos) &&
Definition: settings.hpp:954
acceptor_post_bind_hook_t m_acceptor_post_bind_hook
A hook to be called just after a successful call to bind for acceptor.
Definition: settings.hpp:1730
Derived & cleanup_func(Func &&func) &
Cleanup function.
Definition: settings.hpp:1062
Derived & acceptor_options_setter(acceptor_options_setter_t aos) &
Acceptor options setter.
Definition: settings.hpp:943
std::size_t m_buffer_size
Size of buffer for io operations.
Definition: settings.hpp:1695
auto create_default_shared_object_instance(std::true_type)
Definition: settings.hpp:56
std::unique_ptr< socket_options_setter_t > m_socket_options_setter
Socket options setter.
Definition: settings.hpp:1735
Derived & set_shared_instance(std::shared_ptr< Target > &t, Params &&... params)
Definition: settings.hpp:1674
A fluent style interface for setting http server params.
Definition: settings.hpp:1766
std::chrono::steady_clock::duration m_write_http_response_timelimit
Definition: settings.hpp:1703
extra_data_factory_handle_t m_extra_data_factory
User-data-factory for server.
Definition: settings.hpp:1757
Derived & timer_manager(Params &&... params) &
Definition: settings.hpp:888
Derived & socket_options_setter(socket_options_setter_t sos) &
Socket options setter.
Definition: settings.hpp:971
basic_server_settings_t(std::uint16_t port=8080, asio_ns::ip::tcp protocol=asio_ns::ip::tcp::v4())
Definition: settings.hpp:575
Derived && logger(Params &&... params) &&
Definition: settings.hpp:926
void set_option(const Option &option)
API for setting/getting options.
Definition: settings.hpp:195
A special class for holding actual connection state listener.
Definition: settings.hpp:323
std::chrono::steady_clock::duration m_read_next_http_message_timelimit
Operations timeouts.
Definition: settings.hpp:1700
auto exec_configurator(Configurator &&configurator)
Definition: settings.hpp:1777
A special class for holding actual IP-blocker object.
Definition: settings.hpp:374
std::size_t m_max_pipelined_requests
Max pipelined requests to receive on single connection.
Definition: settings.hpp:1710
An adapter for setting acceptor options before running server.
Definition: settings.hpp:184
std::unique_ptr< socket_options_setter_t > socket_options_setter()
Definition: settings.hpp:988
Derived & extra_data_factory(extra_data_factory_handle_t factory) &
Setter for extra-data-factory.
Definition: settings.hpp:1592
incoming_http_msg_limits_t m_incoming_http_msg_limits
Limits for incoming HTTP messages.
Definition: settings.hpp:1750
Derived && socket_options_setter(socket_options_setter_t sos) &&
Definition: settings.hpp:982
std::chrono::steady_clock::duration m_handle_request_timeout
Definition: settings.hpp:1706
Derived & port(std::uint16_t p) &
Server endpoint.
Definition: settings.hpp:586
cleanup_functor_t m_cleanup_functor
Optional cleanup functor.
Definition: settings.hpp:1743
Derived & request_handler(Params &&... params) &
Definition: settings.hpp:856
Derived && request_handler(Params &&... params) &&
Definition: settings.hpp:866
Derived && port(std::uint16_t p) &&
Definition: settings.hpp:593
bool m_separate_accept_and_create_connect
Do separate an accept operation and connection instantiation.
Definition: settings.hpp:1740
Derived & separate_accept_and_create_connect(bool do_separate) &noexcept
Do separate an accept operation and connection instantiation.
Definition: settings.hpp:1039
std::unique_ptr< acceptor_options_setter_t > acceptor_options_setter()
Definition: settings.hpp:960
asio_ns::ip::tcp::acceptor & m_acceptor
Definition: settings.hpp:223
A special indicator for the case when IP address for a server is not set explicitly.
Definition: settings.hpp:449
std::shared_ptr< Listener > m_connection_state_listener
Definition: settings.hpp:325
std::unique_ptr< timer_factory_t > m_timer_factory
Timers factory.
Definition: settings.hpp:1716
void get_option(Option &option)
Definition: settings.hpp:209
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, optional_t< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in optional_t<Value_Type> if parameter exists ...
Definition: value_or.hpp:64