Restinio Versions Save

Cross-platform, efficient, customizable, and robust asynchronous HTTP(S)/WebSocket server C++ library with the right balance between performance and ease of use

v.0.7.2

3 months ago

It's a maintenance release. If fixes several issues related to RESTinio's dependencies:

  • #207,
  • #208,
  • and #209 (thanks to @yurkoy).

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.

v.0.7.1

4 months ago

It's a maintenance release.

It fixes #198, #199, #200, #201, #203, #204.

v.0.7.0

6 months ago

This is the first significant release since v.0.6.13 and there are several breaking changes.

  • Switch to C++17. Since v.0.7.0 RESTinio requires C++17 as the minimal C++ standard.
  • Switch to nodejs/llhttp library for parsing HTTP requests. Previous versions of RESTinio used nodejs/http-parser, but it is now deprecated and no longer maintained. Since v.0.7.0 RESTinio uses nodejs/llhttp.
  • No more external projects for optional, variant and string_view. After switching to C++17 RESTinio uses std::optional, std::variant and std::string_view. Note that for the expected class RESTinio still needs the expected-lite project as a dependency.
  • Switch to Catch2 v3. The Catch2 library is used in RESTinio for testing. The first versions of Catch2 were header-only, but since v3 the Catch2 needs to be compiled as a library. Since v.0.7.0 RESTinio uses Catch2 v3 and can’t be used with previous versions of Catch2 library.
  • The Clara library is no longer used in RESTinio samples/tests/benchmarks. Parsing of command line arguments in some samples/tests/benchmarks becomes more simple and arguments with long names can’t be shortened now. It means that if --address is required then it can’t be specified as --addr.
  • The RapidJSON/json_dto libraries are no longer used in RESTinio samples/tests/benchmarks.
  • CMake is now the only build system supported. The previous versions of RESTinio used CMake and our own Mxx_ru build systems. Since v.0.7.0 only CMake is used. But Mxx_ru is still in use for managing dependencies.
  • RESTinio's CMake scripts have been refactored significantly. Most of the old CMake variables/options used for the configuration (like 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.
  • Several classes/methods/functions marked as deprecated in previous versions are now removed.
  • The core 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.
  • The format and behavior of 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.
  • Added support of chains of asynchronous handlers. Please see the corresponding section in the documentation for more details.
  • Added a basic support for chunk extensions in incoming requests.

v.0.6.19

9 months ago

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

v.0.6.18

1 year ago

This is a bug-fix release.

Thanks to @horu for PR (#179) with the fix.

v.0.6.17

1 year ago

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).

v.0.6.16

1 year ago

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.

v.0.6.15

1 year ago

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.

v.0.6.14

2 years ago

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.

v.0.6.13

3 years ago

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.