RESTinio
Loading...
Searching...
No Matches
traits.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
5/*!
6 HTTP server traits.
7*/
8
9#pragma once
10
11#include <restinio/request_handler.hpp>
12#include <restinio/asio_timer_manager.hpp>
13#include <restinio/null_logger.hpp>
14#include <restinio/connection_state_listener.hpp>
15#include <restinio/ip_blocker.hpp>
16#include <restinio/default_strands.hpp>
17#include <restinio/connection_count_limiter.hpp>
18
19#include <restinio/utils/metaprogramming.hpp>
20
21namespace restinio
22{
23
24namespace details
25{
26
28{
29
30template< typename, typename, typename = restinio::utils::metaprogramming::void_t<> >
31struct valid_handler_type : public std::false_type {};
32
33template< typename Handler, typename Extra_Data_Factory >
35 Handler,
39 std::is_same<
41 decltype(std::declval<Handler>()(
42 std::declval<
45 >
46 >()))
47 >::value,
48 bool
49 >
50 >
51 > : public std::true_type
52{};
53
54} /* namespace valid_request_handler_type_check */
55
56//
57// autodetect_request_handler_type
58//
59/*!
60 * @brief A special type to be used as indicator that the type of
61 * a request handler should be automatically detected.
62 *
63 * In versions prior to 0.6.13 request-handlers in RESTinio have the
64 * same format. But since v.0.6.13 the actual type of request-handler
65 * is dependent on extra-data-factory type. It means that if a user
66 * defines own extra-data-factory for server's traits then user also
67 * has to define own request-handler type:
68 *
69 * @code
70 * struct my_extra_data_factory {...};
71 *
72 * struct my_traits : public restinio::default_traits_t {
73 * using extra_data_factory_t = my_extra_data_factory;
74 * using request_handler_t = std::function<
75 * restinio::request_handling_status_t(
76 * restinio::generic_request_handle_t<
77 * my_extra_data_factory::data_t>)
78 * >;
79 * };
80 * @endcode
81 *
82 * But this is a boring and error-prone task. So RESTinio allows a user
83 * to specify only `extra_data_factory_t` type and skip the definition
84 * of `request_handler_t`. That definition will be performed automatically.
85 *
86 * The actual detection of request-handler type is performed by
87 * using specialization of actual_request_handler_type_detector for
88 * autodetect_request_handler_type.
89 *
90 * @since v.0.6.13
91 */
93
94//
95// actual_request_handler_type_detector
96//
97/*!
98 * @brief A metafunction for the detection of type of a request-handler.
99 *
100 * @since v.0.6.13
101 */
102template<
103 typename Request_Handler,
104 typename Extra_Data_Factory >
106{
107 static_assert(
111 >::value,
112 "Request_Handler should be invocable with "
113 "generic_request_handle_t<Extra_Data_Factory::data_t>" );
114
115 using request_handler_t = Request_Handler;
116};
117
118/*!
119 * @brief Special version of metafunction %actual_request_handler_type_detector
120 * for the case of %autodetect_request_handler_type.
121 *
122 * @since v.0.6.13
123 */
124template< typename Extra_Data_Factory >
133
134} /* namespace details */
135
136//
137// traits_t
138//
139
140template <
141 typename Timer_Manager,
142 typename Logger,
143 typename Request_Handler = details::autodetect_request_handler_type,
144 typename Strand = default_strand_t,
145 typename Socket = asio_ns::ip::tcp::socket >
147{
148 /*!
149 * @brief A type for HTTP methods mapping.
150 *
151 * If RESTinio is used with vanila version of http_parser then
152 * the default value of http_methods_mapper_t is enough. But if a user
153 * uses modified version of http_parser with support of additional,
154 * not-standard HTTP methods then the user should provide its
155 * http_methods_mapper. For example:
156 * \code
157 * // Definition for non-standard HTTP methods.
158 * // Note: values of HTTP_ENCODE and HTTP_DECODE are from modified
159 * // http_parser version.
160 * constexpr const restinio::http_method_id_t http_encode(HTTP_ENCODE, "ENCODE");
161 * constexpr const restinio::http_method_id_t http_decode(HTTP_DECODE, "DECODE");
162 *
163 * // Definition of non-standard http_method_mapper.
164 * struct my_http_method_mapper {
165 * inline constexpr restinio::http_method_id_t
166 * from_nodejs(int value) noexcept {
167 * switch(value) {
168 * case HTTP_ENCODE: return http_encode;
169 * case HTTP_DECODE: return http_decode;
170 * default: return restinio::default_http_methods_t::from_nodejs(value);
171 * }
172 * }
173 * };
174 * ...
175 * // Make a custom traits with non-standard http_method_mapper.
176 * struct my_server_traits : public restinio::default_traits_t {
177 * using http_methods_mapper_t = my_http_method_mapper;
178 * };
179 * \endcode
180 *
181 * @since v.0.5.0
182 */
184
185 /*!
186 * @brief A type for connection state listener.
187 *
188 * By default RESTinio doesn't inform about changes with connection state.
189 * But if a user specify its type of connection state listener then
190 * RESTinio will call this listener object when the state of connection
191 * changes.
192 *
193 * An example:
194 * @code
195 * // Definition of user's state listener.
196 * class my_state_listener {
197 * ...
198 * public:
199 * ...
200 * void state_changed(const restinio::connection_state::notice_t & notice) noexcept {
201 * ... // some reaction to state change.
202 * }
203 * };
204 *
205 * // Definition of custom traits for HTTP server.
206 * struct my_server_traits : public restinio::default_traits_t {
207 * using connection_state_listener_t = my_state_listener;
208 * };
209 * @endcode
210 *
211 * @since v.0.5.1
212 */
214
215 /*!
216 * @brief A type for IP-blocker.
217 *
218 * By default RESTinio's accepts all incoming connections.
219 * But since v.0.5.1 a user can specify IP-blocker object that
220 * will be called for every new connection. This IP-blocker can
221 * deny or allow a new connection.
222 *
223 * Type of that IP-blocker object is specified by typedef
224 * ip_blocker_t.
225 *
226 * An example:
227 * @code
228 * // Definition of user's IP-blocker.
229 * class my_ip_blocker {
230 * ...
231 * public:
232 * ...
233 * restinio::ip_blocker::inspection_result_t
234 * state_changed(const restinio::ip_blocker::incoming_info_t & info) noexcept {
235 * ... // some checking for new connection.
236 * }
237 * };
238 *
239 * // Definition of custom traits for HTTP server.
240 * struct my_server_traits : public restinio::default_traits_t {
241 * using ip_blocker_t = my_ip_blocker;
242 * };
243 * @endcode
244 *
245 * @since v.0.5.1
246 */
248
249 using timer_manager_t = Timer_Manager;
250 using logger_t = Logger;
251 using request_handler_t = Request_Handler;
252 using strand_t = Strand;
253 using stream_socket_t = Socket;
254
255 /*!
256 * @brief A flag that enables or disables the usage of connection count
257 * limiter.
258 *
259 * Since v.0.6.12 RESTinio allows to limit the number of active
260 * parallel connections to a server. But the usage of this limit
261 * should be turned on explicitly. For example:
262 * @code
263 * struct my_traits : public restinio::default_traits_t {
264 * static constexpr bool use_connection_count_limiter = true;
265 * };
266 * @endcode
267 * In that case there will be `max_parallel_connections` method
268 * in server_settings_t type. That method should be explicitly
269 * called to set a specific limit (by the default there is no
270 * limit at all):
271 * @code
272 * restinio::server_settings_t<my_traits> settings;
273 * settings.max_parallel_connections(1000u);
274 * @endcode
275 *
276 * @since v.0.6.12
277 */
278 static constexpr bool use_connection_count_limiter = false;
279
280 /*!
281 * @brief The type of extra-data-factory.
282 *
283 * By the default RESTinio doesn't hold any additional data for a
284 * request object. But if a user has to store some user-specific
285 * data inside a request object the user has to do the following
286 * steps:
287 *
288 * The first one is the definition of factory type that should
289 * look like:
290 * @code
291 * class some_extra_data_factory {
292 * public:
293 * using data_t = ...;
294 *
295 * void make_within(restinio::extra_data_buffer_t<data_t> buf);
296 * };
297 * @endcode
298 * Where the name `data_t` should define a name of type to incorporated
299 * into request object.
300 * And the method `make_within` should call a placement new for
301 * type `data_t` to construct a new object of `data_t` inside the
302 * buffer `buf`:
303 * @code
304 * void some_extra_data_factory::make_within(
305 * restinio::extra_data_buffer_t<data_t> buf) {
306 * new(buf.get()) data_t{...};
307 * }
308 * @endcode
309 *
310 * The second step is the definition of extra-data-factory in server's traits:
311 * @code
312 * struct my_traits : public restinio::default_traits_t {
313 * using extra_data_factory_t = some_extra_data_factory;
314 * };
315 * @endcode
316 *
317 * The third step is the creation of the extra-data-factory instance and
318 * passing it to server settings:
319 * @code
320 * restino::run(on_thread_pool<my_traits>(16)
321 * .port(...)
322 * .address(...)
323 * .extra_data_factory(std::make_shared<some_extra_data_factory>(..))
324 * .request_handler(...)
325 * ...
326 * );
327 * @endcode
328 * Please note that the third step is not necessary if extra-data-factory
329 * type is DefaultConstructible. In that case an instance of
330 * extra-data-factory will be created automatically.
331 *
332 * Please note that if RESTinio's server is used with express-like or
333 * easy_parser-based routers then `request_handler_t` should be
334 * defined with the respect to extra-data-factory type:
335 * @code
336 * struct my_extra_data_factory {
337 * struct data_t {...};
338 *
339 * void make_within(restinio::extra_data_buffer_t<data_t> buf) {
340 * new(buf.get()) data_t{};
341 * }
342 * };
343 *
344 * using my_router = restinio::router::generic_express_router_t<
345 * restinio::router::std_regex_engine_t,
346 * my_extra_data_factory
347 * >;
348 *
349 * struct my_traits : public restinio::default_traits_t {
350 * using extra_data_factory_t = my_extra_data_factory;
351 * using request_handler_t = my_router;
352 * };
353 * @endcode
354 *
355 * @since v.0.6.13
356 */
358};
359
360//
361// request_handler_type_from_traits_t
362//
363/*!
364 * @brief A metafunction for extraction a request-handler type from
365 * server's traits.
366 *
367 * This metafunction is necessary because `request_handler_t` in
368 * Traits can be an alias for details::autodetect_request_handler_type.
369 * Because of that details::actual_request_handler_type_detector metafunction
370 * is invoked for the detection of request-handler type.
371 *
372 * @since v.0.6.13
373 */
374template< typename Traits >
377 typename Traits::request_handler_t,
378 typename Traits::extra_data_factory_t
380
381//
382// generic_request_type_from_traits_t
383//
384/*!
385 * @brief A metafunction for the detection of actual type of request-object
386 * from server's traits.
387 *
388 * The actual type of request-object depends from extra-data-factory.
389 * This metafunction detect the actual type with the respect to the
390 * definition of `extra_data_factory_t` inside Traits.
391 *
392 * @since v.0.6.13
393 */
394template< typename Traits >
396 generic_request_t< typename Traits::extra_data_factory_t::data_t >;
397
398//
399// single_thread_traits_t
400//
401
402template <
403 typename Timer_Manager,
404 typename Logger,
408
409//
410// default_traits_t
411//
412
414
415/*!
416 * \brief Default traits for single-threaded HTTP-server.
417 *
418 * Uses default timer manager. And null logger.
419 *
420 * Usage example:
421 * \code
422 * struct my_traits : public restinio::default_single_thread_traits_t {
423 * using logger_t = my_special_single_threaded_logger_type;
424 * };
425 * \endcode
426 *
427 * \since
428 * v.0.4.0
429 */
433
434} /* namespace restinio */
The default implementation for http_method_mapper.
typename details::actual_request_handler_type_detector< typename Traits::request_handler_t, typename Traits::extra_data_factory_t >::request_handler_t request_handler_type_from_traits_t
A metafunction for extraction a request-handler type from server's traits.
Definition traits.hpp:375
asio_ns::strand< default_asio_executor > default_strand_t
A typedef for the default strand type.
generic_request_t< typename Traits::extra_data_factory_t::data_t > generic_request_type_from_traits_t
A metafunction for the detection of actual type of request-object from server's traits.
Definition traits.hpp:395
request_handling_status_t
Request handling status.
Special version of metafunction actual_request_handler_type_detector for the case of autodetect_reque...
Definition traits.hpp:128
std::function< request_handling_status_t( generic_request_handle_t< typename Extra_Data_Factory::data_t >) > request_handler_t
Definition traits.hpp:129
A metafunction for the detection of type of a request-handler.
Definition traits.hpp:106
A special type to be used as indicator that the type of a request handler should be automatically det...
Definition traits.hpp:92
The default no-op IP-blocker.
The default extra-data-factory to be used in server's traits if a user doesn't specify own one.
Timer_Manager timer_manager_t
Definition traits.hpp:249
no_extra_data_factory_t extra_data_factory_t
The type of extra-data-factory.
Definition traits.hpp:357
Socket stream_socket_t
Definition traits.hpp:253
connection_state::noop_listener_t connection_state_listener_t
A type for connection state listener.
Definition traits.hpp:213
default_http_methods_t http_methods_mapper_t
A type for HTTP methods mapping.
Definition traits.hpp:183
Request_Handler request_handler_t
Definition traits.hpp:251
ip_blocker::noop_ip_blocker_t ip_blocker_t
A type for IP-blocker.
Definition traits.hpp:247
static constexpr bool use_connection_count_limiter
A flag that enables or disables the usage of connection count limiter.
Definition traits.hpp:278