Traits
List of types that must be defined be Traits
timer_manager_t
defines the logic of how timeouts are managed;logger_t
defines logger that is used by RESTinio to track its inner logic;request_handler_t
defines a function-like type to be used as request handler;strand_t
- defines a class that is used by connection as a wrapper for its callback-handlers running onasio::io_context
thread(s) in order to guarantee serialized callbacks invocation (see asio doc). Actually, there are two options for the strand type:asio::strand<asio::executor>
andasio::executor
. The first is a real strand that guarantees serialized invocation and the second one is simply a default executor to eliminate unnecessary overhead when runningasio::io_context
on a single thread;stream_socket_t
is a customization point that tells RESTinio what type of socket used for connections. This parameter allows restinio to support TLS connection (see TLS support);http_method_mapper_t
is a mapper from integer codes of HTTP methods from http_parser library to RESTinio’shttp_method_id_t
instances;connection_state_listener_t
is a customization point that tells RESTInio what type of connection state listener should be used (see Connection state listener).ip_blocker_t
is a customization point that tells RESTInio what type of IP-blocker should be used (see IP-blocker).extra_data_factory_t
defines what extra-data should be incorporated into a request object (see Extra-data in request object).
timer_manager_t
timer_manager_t
- defines a timeout controller logic.
It must define two nested types.
The first one is timer_guard_t
with the following interface:
class timer_guard_t
{
public:
// Schedule a checking of timed out operations
// after the time interval specified by timer-manager.
void schedule(
// Weak pointer to object to check timed out ops.
// tcp_connection_ctx_weak_handle_t = std::weak_ptr< tcp_connection_ctx_base_t >
tcp_connection_ctx_weak_handle_t weak_handle );
// Cancel timeout guard if any.
void cancel();
};
To understand the ground idea behind timer managers it is needed to clarify on
tcp_connection_ctx_base_t
a weak pointer of which is passed to
timer_guard_t::schedule(). A class
tcp_connection_ctx_base_t has a virtual method:
// Check timeouts for all activities.
virtual void check_timeout(
// A handle to itself (eliminates one shared_ptr instantiation).
std::shared_ptr< tcp_connection_ctx_base_t > & self ) = 0;
Internal classes that inherit from tcp_connection_ctx_base_t
implement this
method to initiate a check whether there are a timed out operations. So
timer_guard_t::schedule()
timer guard must simply store a weak pointer to
tcp_connection_ctx_base_t
somewhere and try to invoke check_timeout()
after some period of time that is specified by timer manager. Here is an
example of how to try to invoke check_timeout()
:
// restinio::tcp_connection_ctx_weak_handle_t weak_handle;
if( auto h = weak_handle.lock() )
{
// Now h is a shared pointer to an exiting object.
h->check_timeout( h );
}
Suppose timer manager sets a time period for checking to 1 second, so each second a context object of a given connection will check if any timeout happened. Between two sequential checks, connection context object may change the actual operation that is tracked for timeout many times.
A timer_guard_t::cancel()
method must cancel scheduled check of a given
timer_guard.
An instance of timer_guard_t
is stored in each connection
managed by RESTinio and to create it timer_manager_t
must define
the following method:
class timer_manager_t
{
public:
// ...
// struct/class timer_guard_t{ ... };
// or
// using timer_guard_t = ...;
// Create guard for connection.
timer_guard_t create_timer_guard();
// ...
};
The second type nested in timer_manager_t
must be factory_t
,
that must implement create(asio::io_context&)
method:
struct factory_t
{
/* Extra parameters for creating timer manager */
auto create( asio::io_context & io_context ) const
{
return std::make_shared< timer_manager_t >( /* params */ );
}
};
Nested factory type is needed for holding parameters of a timer manager that
come from settings. Timer manager itself might need a reference to
asio::io_context
on which server runs, and it is not available on the level
of settings object. So the creation of timer instance is done in two steps. The first
step - the factory is created in server settings and stores params that are needed
for creating timer manager. The second step - when the server is instantiated (hence
asio::io_context
is known) a timer manager is created using the factory.
RESTinio comes with a set of ready-to-use timer_manager_t
implementation:
null_timer_manager_t
– noop timer guards, they produce timer guards that do nothing (when no control needed). See restinio/null_timer_manager.hpp;asio_timer_manager_t
– timer guards implemented with asio timers. See restinio/asio_timer_manager.hpp;so5::so_timer_manager_t
– timer guards implemented with SObjectizer timers. See restinio/so5/so_timer_manager.hpp. Note thatrestinio/so5/so_timer_manager.hpp
header file is not included byrestinio/core.hpp
, so it needs to be included separately.
If the timer_manager requires initial parameters then such parameters can be
specified by using timer_manager
method in settings:
restinio::run(
restinio::on_this_thread()
// Settings tuning starts here.
.port(8080)
.address("localhost")
.timer_manager(... /* Parameters for the timer manager */)
.request_handler(...)
// Settings tuning is completed.
);
The list of parameters to be passed to timer_manager
method depends on
the type of the timer_manager. For example, the standard asio_timer_manager_t
accepts just one parameter: duration of now tick of the timer:
restinio::run(
restinio::on_this_thread()
// Settings tuning starts here.
.port(8080)
.address("localhost")
// Change the default one-second timer interval to more precise one.
.timer_manager(std::chrono::milliseconds{250})
.request_handler(...)
// Settings tuning is completed.
);
logger_t
logger_t
- defines a logger implementation.
It must support the following interface:
class null_logger_t
{
public:
template< typename Msg_Builder >
void trace( Msg_Builder && mb );
template< typename Msg_Builder >
void info( Msg_Builder && mb );
template< typename Msg_Builder >
void warn( Msg_Builder && mb );
template< typename Msg_Builder >
void error( Msg_Builder && mb );
};
Msg_Builder
is lambda that returns a message to log out.
This approach allows a compiler to optimize logging when it is possible,
see null_logger_t.
For implementation example see ostream_logger_t.
request_handler_t
request_handler_t
- is a key type for request handling process.
It must be a function-object with the following invocation interface:
template<typename User_Data>
restinio::request_handling_status_t
handler( restinio::generic_request_handle_t<User_Data> req );
See Request handler for more details.
strand_t
strand_t
provides serialized callback invocation for events of a specific
connection. There are two option for strand_t
: asio::strand<asio::executor>
or asio::executor
.
By default asio::strand<asio::executor>
is used,
it guarantees serialized chain of callback invocation.
But if asio::io_context
runs on a single thread there is no need
to use asio::strand
because there is no way to run callbacks in parallel.
So in such cases, it is enough to use asio::executor
directly and
eliminate the overhead of asio::strand
.
stream_socket_t
stream_socket_t
allows to customize underlying socket type,
so it possible to create https server using identical interface (see TLS support).
http_method_mapper_t
Since v.0.5.0 RESTinio allows to used customized versions of http_parser
libraries. It means that a customized http_parser can support some additional
HTTP methods. For example, someone can fork http_parser and add support for
ENCODE and DECODE custom methods to that fork. Type http_method_mapper_t
allows to bring the support of that custom methods to RESTinio.
A user-supplied http_method_mapper_t
type should contain one static and
public method from_nodejs
with the following signature:
static restinio::http_method_id_t
from_nodejs( int http_parser_code ) noexcept;
Method from_nodejs
will be called when RESTinio receives HTTP method code
from http_parser. Value returned this method will be stored in http_request_header_t
object associated with the corresponding request.
By default http_method_mapper_t
is just a typedef for
restinio::default_http_methods_t
type. A user have to define its
http_method_mapper_t
only if a customized http_parser is used and that
parser introduces new non-standard HTTP methods.
An example of customization of RESTinio to use non-standard HTTP methods can look like that:
// Definitions of new HTTP methods.
constexpr const restinio::http_method_id_t http_encode{HTTP_ENCODE, "ENCODE"};
constexpr const restinio::http_method_id_t http_decode{HTTP_DECODE, "DECODE"};
// Definition of custom http_method_mapper.
struct my_http_method_mapper {
inline static constexpr restinio::http_method_id_t
from_nodejs(int code) noexcept {
switch(code) {
case HTTP_ENCODE: return http_encode;
case HTTP_DECODE: return http_decode;
default: return restinio::default_http_methods_t::from_nodejs(code);
}
}
};
connection_state_listener_t
This type allows to specify what type of connection state listener should be
used for RESTinio’s server. By default the value
restinio::connection_state::noop_listener_t
is used.
See Connection state listener for more details.
ip_blocker_t
This type allows to specify what type of IP-blocker should be
used for RESTinio’s server. By default the value
restinio::ip_blocker::noop_ip_blocker_t
is used.
See IP-blocker for more details.
extra_data_factory_t
If a user wants to incorporate some extra-data into a request object then
he/she have to define own extra-data-factory type and specify the name of
that type as extra_data_factory_t
inside Traits.
See Extra-data in request object for more details.