Cross-platform, efficient, customizable, and robust asynchronous HTTP(S)/WebSocket server C++ library with the right balance between performance and ease of use
It's a maintenance release. If fixes several issues related to RESTinio's dependencies:
NOTE! If you have no problem with RESTinio-0.7.1 there is no need to update to v.0.7.2. An update may be necessary if you manage RESTinio's dependencies by yorself.
It's a maintenance release.
It fixes #198, #199, #200, #201, #203, #204.
This is the first significant release since v.0.6.13 and there are several breaking changes.
expected
class RESTinio still needs the expected-lite project as a dependency.--address
is required then it can’t be specified as --addr
.RESTINIO_FIND_DEPS
) have been removed. There are several new variables/options that have to be used since v0.7.0: RESTINIO_ASIO_SOURCE
, RESTINIO_DEP_STANDALONE_ASIO
, RESTINIO_DEP_BOOST_ASIO
, RESTINIO_DEP_LLHTTP
, RESTINIO_DEP_FMT
, RESTINIO_DEP_EXPECTED_LITE
and so on. Please see the corresponding section in the documentation for more details.restinio/all.hpp
header file has been deprecated. It will be removed in v.0.8.0. The new core restinio/core.hpp
header file must be used instead.restinio::on_pool_runner_t::stop
changed. Now it may accept on_error-callback. The default on_error-callback calls std::abort
if an exception is thrown in http_server_t::close_async
.This is a maintenance release.
Asio updated to 1-28-1. fmtlib updated to 10.1.0.
Adaptation for SObjectizer-5.8.0.
Fix for compilation error with GCC-13. Thanks to @bandali0 for PR #183
Fix for #184
This is a bug-fix release.
Thanks to @horu for PR (#179) with the fix.
Since v.0.6.17 RESTinio can be used with fmtlib in FMT_ENFORCE_COMPILE_STRING
mode. In this mode FMT_STRING
macro has to be used for format string in C++11/14/17 for compile-time checking of format string validity.
Now RESTinio checks the presence of FMT_ENFORCE_COMPILE_STRING
and uses FMT_STRING
when it's required.
NOTE. FMT_ENFORCE_COMPILE_STRING
has to be defined before inclusion of any of RESTinio's headers.
fmtlib-9.1.0 in now used inside RESTinio (and included in restinio-0.6.17-full.* archives).
This release adapts RESTinio to fmtlib-9.0.0.
Since v.0.6.16 RESTinio can be used with fmtlib-8 or fmtlib-9, but fmtlib-8 is still used in RESTinio development.
NOTE: restinio-0.6.14-full.* archives contain asio-1-21-1, fmt-8.1.1 and catch-2.13.9. Versions of 3rd party libraries in restinio/third_party updated to the latest versions:
expected-lite at commit 34524d46e538f1e6ed114d8f8409f7cd173d96e6. optional-lite at commit ea502a6472c85dbc0174764df218a0c3443c6772. string-view-lite at commit f7aca36f5caa05e451f6887aa707df89197e6de6. variant-lite at commit f1af3518e4c28f12b09839b9d2ee37984cbf137a.
This is a maintenance release.
A fix for CMake script for case when RESTINIO_FIND_DEPS=ON
and RESTINIO_FMT_HEADER_ONLY=OFF
(#159).
Usage of std::aligned_storage_t
in implementation of writable_item_t
has been removed (it's deprecated in C++23).
In some places std::launder
is used (if available) to avoid UB accessing a pointer after placement new.
NOTE: restinio-0.6.14-full.* archives contain asio-1-21-1, fmt-8.1.1 and catch-2.13.9. Versions of 3rd party libraries in restinio/third_party
weren't upgraded.
This is just a maintenance release.
NOTE: restinio-0.6.14-full.* archives contain asio-1-21-1 and fmt-8.0.1. Versions of other dependencies are not changed.
This version introduces a couple of new big features and contains several changes some of that can affect existing code.
A new value not_handled
added to request_handling_status_t
enumeration (+ new helper function request_not_handled()
). This value should be returned if a request-handler doesn't accept nor reject the current request and some other request-handler should be tried (if such a handler exists). If all request-handlers called for request processing return not_handled
then RESTinio treats that value as rejected
.
It's possible now to incorporate some additional (extra) data into a request-object. To do so a user has to perform the following steps:
Define a type for holding such an extra data:
struct per_request_data {
user_indentity user_info_;
...
};
Define a extra-data-factory that should look like:
struct my_extra_data_factory {
using data_t = per_request_data;
void make_within(restinio::extra_data_buffer_t<data_t> buf) {
new(buf.get()) data_t{};
}
};
Or, if extra-data-factory is a simple and stateless object as shown above:
using my_extra_data_factory = restinio::simple_extra_data_factory_t<per_request_data>;
Specify my_extra_data_factory
in server's traits:
struct my_traits : public restinio::default_traits_t {
using extra_data_factory_t = my_extra_data_factory;
};
Change the format of request-handlers this way:
restinio::request_handling_status_t request_handler(
const restinio::generic_request_handle_t<per_request_data> & req);
// or
restinio::request_handling_status_t request_handler(
const restinio::generic_request_handle_t<my_extra_data_factory::data_t> & req);
Extra-data is available inside a request-handler via new method request_t::extra_data
:
restinio::request_handling_status_t request_handler(
const restinio::generic_request_handle_t<per_request_data> & req)
{
auto & ed = req->extra_data();
...
}
See the documentation for more details.
It's possible now to bind several synchronous request-handlers into a chain (somewhat similar to ExpressJS's middleware):
#include <restinio/all.hpp>
#include <restinio/sync_chain/fixed_size.hpp>
auto incoming_req_logger(const restinio::request_handle_t & req)
{
... // Perform logging.
// Allow the passing of the request to the next handler.
return restinio::request_not_handled();
}
auto mandatory_fields_checker(const restinio::request_handle_t & req)
{
... // Perform all necessary checks.
if(!ok) {
// Negative response has to be sent.
return req->create_response(restinio::status_bad_request())
...
.done();
}
// Allow the passing of the request to the next handler.
return restinio::request_not_handled();
}
auto permissions_checker(const restinio::request_handle_t & req)
{
... // Check user credentials and permissions.
if(!ok) {
// Negative response has to be sent.
return req->create_response(restinio::status_unauthorized())
...
.done();
}
// Allow the passing of the request to the next handler.
return restinio::request_not_handled();
}
auto actual_processor(const restinio::request_handle_t & req)
{
... // Do actual request processing.
return restinio::request_accepted();
}
struct my_traits : public restinio::default_traits_t {
// Change the type of request handler.
using request_handler_t = restinio::sync_chain::fixed_size_chain_t<4>;
};
restinio::run(restinio::on_this_thread<my_traits>()
.port(...)
.address(...)
.request_handler(
// Enumerate all handlers in the chain in the order of invocation.
incoming_req_logger,
mandatory_fields_checker,
permissions_checker,
actual_processor)
...
);
When a new incoming request will be parsed the RESTinio will call incoming_req_logger
, then mandatory_req_logger
, then (if necessary) permissions_checker
, and only then (if necessary) actual_processor
.
See the documentation for more details.