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

Overview

What Is RESTinio?

RESTinio is a header-only C++14 library that gives you an embedded HTTP/Websocket server. It is based on standalone version of ASIO and targeted primarily for asynchronous processing of HTTP-requests. Since v.0.4.1 Boost::ASIO (1.66 or higher) is also supported (see notes on building with Boost::ASIO).

A Very Basic Example Of RESTinio

Consider the task of writing a C++ application that must support some REST API, RESTinio represents our solution for that task. Currently it is in stable beta state. Lets see how it feels like in the simplest case:

#include <restinio/all.hpp>
int main()
{
    restinio::run(
        restinio::on_this_thread()
        .port(8080)
        .address("localhost")
        .request_handler([](auto req) {
            return req->create_response().set_body("Hello, World!").done();
        }));
    return 0;
}

Server runs on the main thread, and respond to all requests with hello-world message. Of course you've got an access to the structure of a given HTTP request, so you can apply a complex logic for handling requests.

Features

  • Async request handling. Cannot get the response data immediately? That's ok, store request handle somewhere and/or pass it to another execution context and get back to it when the data is ready.
  • HTTP pipelining. Works well with async request handling. It might increase your server throughput dramatically.
  • Timeout control. RESTinio can take care of bad connection that are like: send "GET /" and then just stuck.
  • Response builders. Need chunked-encoded body - then RESTinio has a special response builder for you (obviously it is not the only builder).
  • ExpressJS-like request routing (see an example below).
  • An experimental typesafe request router that allows avoiding problems of ExpressJS-like router with help of static checks from C++ compiler.
  • A possibility to chain several request-handlers (somewhat similar to ExpressJS's middleware).
  • Working with query string parameters.
  • Several ready-to-use helpers for working with HTTP headers (for example, the support for HTTP headers related to file uploading).
  • Supports sending files and its parts (with sendfile on linux/unix and TransmitFile on windows).
  • Supports compression (deflate, gzip).
  • Supports TLS (HTTPS).
  • Basic websocket support. Simply restinio::websocket::basic::upgrade() the request handle and start websocket session on a corresponding connection.
  • Can run on external asio::io_context. RESTinio is separated from execution context.
  • Some tune options. One can set acceptor and socket options. When running RESTinio on a pool of threads connections can be accepted in parallel.

Enhanced Example With Express Router

#include <restinio/all.hpp>

using namespace restinio;

template<typename T>
std::ostream & operator<<(std::ostream & to, const optional_t<T> & v) {
    if(v) to << *v;
    return to;
}

int main() {
    // Create express router for our service.
    auto router = std::make_unique<router::express_router_t<>>();
    router->http_get(
            R"(/data/meter/:meter_id(\d+))",
            [](auto req, auto params) {
                const auto qp = parse_query(req->header().query());
                return req->create_response()
                        .set_body(
                                fmt::format("meter_id={} (year={}/mon={}/day={})",
                                        cast_to<int>(params["meter_id"]),
                                        opt_value<int>(qp, "year"),
                                        opt_value<int>(qp, "mon"),
                                        opt_value<int>(qp, "day")))
                        .done();
            });

    router->non_matched_request_handler(
            [](auto req){
                return req->create_response(restinio::status_not_found()).connection_close().done();
            });

    // Launching a server with custom traits.
    struct my_server_traits : public default_single_thread_traits_t {
        using request_handler_t = restinio::router::express_router_t<>;
    };

    restinio::run(
            restinio::on_this_thread<my_server_traits>()
                    .address("localhost")
                    .request_handler(std::move(router)));

    return 0;
}

License

RESTinio is distributed under BSD-3-CLAUSE license.

How To Use It?

The full documentation for RESTinio can be found here.

More

Issues
  • acceptor.h seems to block

    acceptor.h seems to block

    Hi,

    I am using restinio on a server receiving a lot of connections. I saw that sometimes, the server is hanging and doesn't accepts any new connections (but current connections continue to work without issues).

    Just before hanging, this is what I see in the logs:

    an exception in 'accept_current_connection': remote_endpoint: Transport endpoint is not connected
    

    So, my assumption is that https://github.com/Stiffstream/restinio/blob/bd4382c2fd355efa8ee2f1fffe62f0134b472e30/dev/restinio/impl/acceptor.hpp#L308 is not recovering after that exception. (This line is throwing the exception: https://github.com/Stiffstream/restinio/blob/bd4382c2fd355efa8ee2f1fffe62f0134b472e30/dev/restinio/impl/acceptor.hpp#L372)

    I'm currently investigating, but if you have any clue, it will be appreciated :)

    opened by AmarOk1412 35
  • user_controlled_output_t closes the connection on .flush()

    user_controlled_output_t closes the connection on .flush()

    Hi Stiffstream,

    I'm trying to implement a user_controlled_output_t as a response inside my get handler. However, the connection is getting closed on a flush() as seen in this simple:

    request_status Server::get(restinio::request_handle_t request,
                             restinio::router::route_params_t params)
    {
        printf("connection_id: %lu\n", request->connection_id());
    
        using output_t = restinio::user_controlled_output_t;
        auto response = this->init_http_resp(request->create_response<output_t>(
    
        ));
        //response.set_content_length(request->body().size());
        response.flush();
        std::this_thread::sleep_for(std::chrono::seconds(2));
    
        std::string part1 = "i like";
        response.set_body(part1);
        response.set_content_length(part1.size());
        response.flush();
        std::this_thread::sleep_for(std::chrono::seconds(2));
    
        std::string part2 = " waffles!";
        response.set_body(part2);
        response.set_content_length(part2.size());
        response.flush();
        std::this_thread::sleep_for(std::chrono::seconds(2));
    
        return response.done();
    }
    

    I'm implementing your amazing RESTinio server into OpenDHT project that needs to be able to send get responses by parts i.e. head first then, once a callback is fired for a value found on a node, another one and so forth until done callback.

    I also went into debugging your code base with gdb and the flags are properly set:

    gdb$ b /usr/local/include/restinio/impl/connection.hpp:794
    Breakpoint 1 at 0xb10b1: file /usr/local/include/restinio/impl/connection.hpp, line 794.
    ...
    gdb$ p response_output_flags
    $1 = {m_response_parts = restinio::response_parts_attr_t::not_final_parts, m_response_connection = restinio::response_connection_attr_t::connection_keepalive}
    

    But it seems that the connection is getting closed on a flush() which is strange to me because the definition of a flush would be considered a different one from done() in terms of not closing the connection with response_parts_attr_t::not_finals_parts whereas a done() is sending response_parts_attr_t::final_parts flag.

    The goal is to be able to perform an async yield like this part that I am removing.

    Thank you for your time!

    Sincerely, Seva

    opened by binarytrails 23
  • Getting the connection state/status

    Getting the connection state/status

    Hi devs,

    We have one last operation on the server called LISTEN which keeps a connection open at the maximum defined delay in the settings handle_request_timeout. Everything is good and I can send chunks and close it using the response with response.connection_close(). I can find its ID with request->connection_id() which returns a connection_id_t.

    However, we need to be able to check the connection state (open, closed) using the connection_id_t or any other object in a different thread to close the connections gracefully in case we shutdown the server as well as use this observer thread to close the active listeners on the OpenDHT thread.

    Thank you for the heads up! :rocket: Seva

    opened by binarytrails 19
  • LGTM pass by value

    LGTM pass by value

    Hello i followed the example from the markdown for creating a request, but now i got this warning from LGTM security services:

    Capture d’écran 2019-08-07 à 19 10 53

    Can we pass the router as const reference, or it's always as copy (like your example)

    opened by Milerius 17
  • Why is http_header_fields_t::find() private?

    Why is http_header_fields_t::find() private?

    Is there a specific reason that all find methods in http_header_fields_t are private? If I want to check for the existence of a field and get its value if it exists, I have to either use has_field and get_field doing the lookup twice, or I could use the public begin and end methods with std::find_if duplicating what find already does.

    opened by rcane 17
  • Error compiling tls_socket_t under MSVC

    Error compiling tls_socket_t under MSVC

    When trying to create a tls-enabled server the MSVC compiler complains about this:

    ...restinio/impl/tls_socket.hpp(93): error C3779: 'restinio::impl::tls_socket_t::lowest_layer': a function that returns 'auto' cannot be used before it is defined
    ...restinio/impl/tls_socket.hpp(60): note: see declaration of 'restinio::impl::tls_socket_t::lowest_layer'
    ...restinio/impl/tls_socket.hpp(93): note: This diagnostic occurred in the compiler generated function 'void restinio::impl::tls_socket_t::cancel(Args &&...)'
    ...
    

    Simply not using lowest_layer() inside tls_socket_t's methods and instead replacing it with m_socket->lowest_layer() fixes the problem.

    opened by rcane 16
  • How best to return a 405 response from express router

    How best to return a 405 response from express router

    I am looking for suggestion, to create example for how someone can return 405 on endpoint.

    For instance for any given route...

    auto router = std::make_unique<router_t>();
    router->http_post("/author/:author", [](auto req, auto param) {
        if(req->header().method() != http_method_post()) {
            return req->create_response(status_method_not_allowed())
                .connection_close().done();
        }
        // Happily process the request
    }
    

    What I would like to avoid is creating routes for every single method for each path and handling all the "bad methods" that I need to block.

    opened by prince-chrismc 13
  • restinio unable to regonize `*!` in url

    restinio unable to regonize `*!` in url

    when request /foo?bar=*, restinio will raise exception:

    restinio error while handling request: invalid non-escaped char with code 0X2A
    

    Also for url /foo?bar=!.

    *! will be not encoded in url in Chrome. One can check the result of encodeURIComponent("!*") in Chrome console.

    opened by zhangzq 12
  • Sendfile works faster for larger files?

    Sendfile works faster for larger files?

    I've been doing benchmarks for multiple web-servers/REST frameworks inlcuding rwasa, asmttpd, C++ REST SDK, Spring MVC, Spring Webflux and Restinio. The performance for sending files with Restinio was among the best. Especially that it didn't have the deadlocking problem serving files with multiple requests that the C++ REST SDK had. However, I've noticed a strange behavior with Restinio: I make 4 comparative benchmarks with Gatling: 2 with 300 simultaneous users and 2 with 3000 users, each one is done with 70 bytes and 700kb files respectively. The smaller file is an HTTP file and the larger one is a binary file. For the larger file the response time has been like this: image

    and for the smaller file like this: image

    As you can see, the smaller file has a larger average time for some reason! I've done that multiple times and always had the same results. Any explanation for that? All the tests were done on the sendfile sample on Linux

    opened by ahmedyarub 12
  • error: exception specification of explicitly defaulted move constructor... in buffers.hpp

    error: exception specification of explicitly defaulted move constructor... in buffers.hpp

    This code was introduced in #53.

    I was trying to compile the example from the README to check whether I am including RESTinio appropriately in my project, but I get this error:

    /Users/Koji/performous/3rdparty/restinio/dev/restinio/buffers.hpp:215:3: error: exception specification of explicitly defaulted move constructor
          does not match the calculated one
                    datasizeable_buf_t( datasizeable_buf_t && ) noexcept = default; // allow only explicit move.
                    ^
    /Users/Koji/performous/3rdparty/restinio/dev/restinio/buffers.hpp:381:3: note: in instantiation of template class
          'restinio::impl::datasizeable_buf_t<fmt::v6::basic_memory_buffer<char, 1, std::__1::allocator<char> > >' requested here
                    alignof( fmt_minimal_memory_buffer_buf_t ) } );
                    ^
    

    I am using XCode's Clang on macOS 10.14.6

    opened by Lord-Kamina 11
  • Empty response with the sendfile operation

    Empty response with the sendfile operation

    Hi,

    I am trying to use the sendfile operation to send a text file, but I get an empty response. This is a minimal example of what I am doing:

    restinio::run(
            restinio::on_this_thread()
              .port(8080)
              .address("localhost")
              .request_handler([](auto req) {
                return req->create_response().append_header(restinio::http_field::content_type, "text/plain; charset=utf-8").set_body(restinio::sendfile("C:/Workspace/test.txt")).done();
              }));
    

    Any help would be much appreciated. Thanks! :)

    opened by govinddanil 10
  • RESTinio can be used in a project where fmtlib is used with FMT_ENFORCE_COMPILE_STRING=1

    RESTinio can be used in a project where fmtlib is used with FMT_ENFORCE_COMPILE_STRING=1

    If fmtlib is used with

    #define FMT_ENFORCE_COMPILE_STRING 1
    

    then all calls to fmt::format should use FMT_STRING for format string.

    An attempt to use RESTinio in such a project leads to compile-time errors in RESTinio's calls to fmt::string.

    It's necessary to adapt RESTinio's usage of fmtlib to scenario when FMT_ENFORCE_COMPILE_STRING is forced.

    opened by eao197 0
  • [idea] Deprecation of RESTINIO_FIND_DEPS in favor of RESTINIO_EXTERNAL_FMT, RESTINIO_EXTERNAL_CATCH2 and so on

    [idea] Deprecation of RESTINIO_FIND_DEPS in favor of RESTINIO_EXTERNAL_FMT, RESTINIO_EXTERNAL_CATCH2 and so on

    Dependency management in CMake scripts started from very simple things but evolved to rather complex scheme that I don't understand fully. Now we have RESTINIO_FIND_DEPS with additional case RESTINIO_USE_EXTERNAL_HTTP_PARSER (and I don't get an idea of RESTINIO_FIND_DEPS=ON and RESTINIO_USE_EXTERNAL_HTTP_PARSER=OFF case) plus RESTINIO_USE_EXTERNAL_*_LITE options.

    Maybe it's better to remove RESTINIO_FIND_DEPS and use new options like RESTINIO_USE_EXTERNAL_FMT, RESTINIO_USE_EXTERNAL_HTTP_PARSER (+RESTINIO_USE_EXTERNAL_UNOFFICIAL_HTTP_PARSER), RESTINIO_USE_EXTERNAL_CATCH2 and other.

    I think that change should lead to change a version number, e.g. 0.7.0 instead of 0.6.15. And that version change can be done during adopting to Catch2 v3.

    v3 of Catch2 is no more single-header header-only library and switching to v3 may require some refactoring of RESTinio's test. It's a significant change to be reflected in RESTinio's version bump.

    opened by eao197 0
  • Upgrade Catch2 to v3

    Upgrade Catch2 to v3

    Catch2 library is used as unit-test framework in the RESTinio development.

    Since v3 Catch2 is no more header-only library: https://github.com/catchorg/Catch2/releases/tag/v3.0.1

    RESTinio have to be updated to Catch2 after Catch2-v3 will be stabilized and got a few correcting releases.

    opened by eao197 0
  • The development of RESTinio has been suspended

    The development of RESTinio has been suspended

    RESTinio is being developed by our small company stiffstream. Nobody pays us for that, we develop RESTinio using our own funds.

    In the past, we got funding by doing custom development and/or maintenance of C/C++ projects by contracts. But the 2020 year was very unsuccessful for us and we didn't get the money we expected to spend for our OpenSource projects in 2021.

    So now we have no resources to work on OpenSource projects including RESTinio and have to suspend the development of RESTinio for some time.

    If you want to see some new functionality in RESTinio, then consider the possibility of ordering an extension of RESTinio on a paid basis.

    You can also help us by spreading info about stiffstream: maybe someone needs the help of experienced C++ developers. The RESTinio project is a good example of our abilities and the quality of our work.

    I want to say "Thanks!" to all who selected RESTinio. Your attention to our project and your feedback was one of the main drivers in RESTinio's development.

    opened by eao197 9
  • How to debug the handlers?

    How to debug the handlers?

    My app showed me an error message:

    ERROR: [connection:5] error while handling request: basic_string::_M_replace_aux
    

    I didn't know where the error cames from (even I compiled in debug mode and run in gdb). What should I do?

    opened by zhangzq 6
Releases(v.0.6.16)
  • v.0.6.16(Jul 12, 2022)

    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.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.16-full.tar.bz2(1.60 MB)
    restinio-0.6.16-full.zip(3.02 MB)
    restinio-0.6.16.tar.bz2(526.10 KB)
    restinio-0.6.16.zip(951.02 KB)
  • v.0.6.15(May 26, 2022)

    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.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.15-full.tar.bz2(1.60 MB)
    restinio-0.6.15-full.zip(3.02 MB)
    restinio-0.6.15.tar.bz2(525.01 KB)
    restinio-0.6.15.zip(949.67 KB)
  • v.0.6.14(Nov 19, 2021)

  • v.0.6.13(Dec 28, 2020)

    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.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.13-full.tar.bz2(1.49 MB)
    restinio-0.6.13-full.zip(2.78 MB)
    restinio-0.6.13.tar.bz2(524.53 KB)
    restinio-0.6.13.zip(947.75 KB)
  • v.0.6.12(Nov 10, 2020)

    A new method incoming_http_msg_limits added to restinio::server_settings_t. This method allows to set up limits for the maximum length of various parts of an incoming HTTP message (like URL, HTTP-field’s name and value):

    struct my_traits : public restinio::default_traits_t { ... };
    
    restinio::server_settings_t<my_traits> settings;
    settings.incoming_http_msg_limits(
       restinio::incoming_http_msg_limits_t{}
          .max_url_size(8000u)
          .max_field_name_size(2048u)
          .max_field_value_size(4096u)
    );
    ...
    auto server = restinio::run_async(
       restinio::own_io_context(),
       std::move(settings),
       std::thread::hardware_concurrency());
    

    A possibility to limit the number of parallel connection has been added:

    struct my_traits : public restinio::default_traits_t {
       // Force the usage of connection count limiter.
       static constexpr bool use_connection_count_limiter = true;
    };
    
    restinio::server_settings_t<my_traits> settings;
    settings.max_parallel_connections(1000u);
    ...
    auto server = restinio::run_async(
       restinio::own_io_context(),
       std::move(settings),
       std::thread::hardware_concurrency());
    

    A support for SObjectizer 5.6/5.7 has been added. Now RESTinio can be user either with SObjectizer 5.5 and SObjectizer 5.6/5.7. The version of SObjectizer is detected automatically. But if a user wants to use SObjectizer 5.6/5.7 he/she should set C++ standard to C++17 manually.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.12-full.tar.bz2(1.40 MB)
    restinio-0.6.12-full.zip(2.58 MB)
    restinio-0.6.12.tar.bz2(515.51 KB)
    restinio-0.6.12.zip(919.51 KB)
  • v.0.6.11(Oct 22, 2020)

    Conversion functions passed to restinio::easy_parser::convert can now return expected_t<T, error_reason_t> as well as just T. Returning expected_t<T, error_reason_t> allows to report conversion errors without throwing an exception. This is a fix for #99.

    A new overload for restinio::server_settings_t::address() method. The new overload accepts an instance of asio::ip::address (or boost::asio::ip::address). This is a fix for #100.

    A new optional post-bind hook added. This hook is called just after a succesful return from bind() for server’s acceptor. A reference to asio::ip::tcp::acceptor is passed to that hook. This new hook can be used for application-specific tuning of bound acceptor or to gathering some information about the acceptor. This is a fix for #126. For example, this code snippet shows how RESTinio server can be started on a random port assigned by the Operating System:

    std::promise<unsigned short> port_promise; // For getting the port.
    auto server = restinio::run_async(
          restinio::use_own_context(),
          restinio::server_settings_t{}
             .address("localhost")
             .port(0u) // Zero means that port will be assigned by the OS.
             .acceptor_post_bind_hook(
                [&port_promise](asio::ip::tcp::acceptor & acceptor) {
                   // Gathering the actual port number.
                   port_promise.set_value(acceptor.local_endpoint().port());
                })
             .request_handler(...),
          4u);
    // Now we can safely get the actual port number from the promise.
    const auto actual_port = port_promise.get_future().get();
    
    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.11-full.tar.bz2(1.39 MB)
    restinio-0.6.11-full.zip(2.56 MB)
    restinio-0.6.11.tar.bz2(509.22 KB)
    restinio-0.6.11.zip(902.35 KB)
  • v.0.6.10(Aug 20, 2020)

  • v.0.6.9(Aug 13, 2020)

    Now RESTinio works with Asio 1.17. Version 0.6.9 can be used with Asio 1.12, 1.14, 1.16, and 1.17.

    Support for incoming requests with chunked encoding has been added. Previous versions of RESTinio didn’t support such requests, HTTP 501 error was returned. Since v.0.6.9 RESTinio accepts such requests and glues all chunks together into the one body. Information about an individual chunk is preserved and is available via request_t::chunked_input_info.

    Since v.0.6.9 the value OFF for CMake-option RESTINIO_ALLOW_SOBJECTIZER is handled differently: all tests/examples/benchmarks those require SObjectizer as a dependency won't be compiled. All other tests/examples will be compiled as usual. There is also a new CMake-option RESTINIO_USE_EXTERNAL_SOBJECTIZER.

    New methods for http_header_fields_t class: remove_all_of and add_field.

    New helpers for parsing the following HTTP-fields: Connection, Host, Transfer-Encoding.

    New tools for easy_parser and HTTP-field parsers: expected_token_p, expected_caseless_token_p, symbol_from_range_p, caseless_exact, caseless_exact_p.

    There are also some thoughts about the future development of RESTinio.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.9-full.tar.bz2(1.38 MB)
    restinio-0.6.9-full.zip(2.54 MB)
    restinio-0.6.9.tar.bz2(504.94 KB)
    restinio-0.6.9.zip(888.40 KB)
  • v.0.6.8.1(Jun 24, 2020)

  • v.0.6.8(May 15, 2020)

    Implementation of extraction of Bearer authentification parameters fixed. Now it looks like:

    #include <restinio/all.hpp>
    #include <restinio/http_field_parser/bearer_auth.hpp>
    ...
    auto on_request(const restinio::request_handle_t & req) {
       using namespace restinio::http_field_parsers::bearer_auth;
       const auto auth_params = try_extract_params(*req,
             restinio::http_field::authorization);
       if(auth_params) { // Parameters successfully extracted.
          if(is_valid_user(auth_params->token)) {
             ...
          }
       }
       ...
    }
    

    New helper function try_parse_field for simplification of HTTP-fields parsing added:

    #include <restinio/all.hpp>
    #include <restinio/helpers/http_fields_parsers/try_parse_field.hpp>
    #include <restinio/helpers/http_fields_parsers/accept.hpp>
    ...
    auto on_request(const restinio::request_handle_t & req) {
       using namespace restinio::http_field_parsers;
       // Try to get and parse the value of `Accept` header.
       const auto parse_result = try_parse_field<accept_value_t>(
             req, restinio::http_field::accept);
       if(const auto * value =
             restinio::get_if<accept_value_t>(&parse_result)) {
          // Value of the field is successfully parsed.
          ... // Some usage of parsed value.
       }
    }
    

    Several new overloads for try_extract_params functions from restinio::http_field_parsers::basic_auth and restinio::http_field_parsers::bearer_auth namespaces. They allow to work with several authentication schemes after the parsing of Authorization (Proxy-Authorization) field:

    auto on_request(const restinio::request_handle_t & req) {
       using namespace restinio::http_field_parsers;
    
       const auto field = try_parse_field<authorization_value_t>(
             req, restinio::http_field::authorization);
       if(const auto * auth = restinio::get_if<authorization_value_t>(field)) {
          // We have valid Authorization field value.
          if("basic" == auth->auth_scheme) {
             // Basic authentification scheme should be used.
             using namespace restinio::http_field_parsers::basic_auth;
             const auto params = try_extract_params(auth->auth_params);
             if(params) { // Parameters successfully extracted.
                if(is_valid_user(params->username, params->password)) {
                   ...
                }
             }
             ...
          }
          else if("bearer" == auth->auth_scheme) {
             // Bearer authentification scheme should be used.
             using namespace restinio::http_field_parsers::bearer_auth;
             const auto params = try_extract_params(auth->auth_params);
             if(auth_params) { // Parameters successfully extracted.
                if(is_valid_user(auth_params->token)) {
                   ...
                }
             }
             ...
          }
          else {
             ... // Handling of different schemes.
          }
       }
    }
    
    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.8-full.tar.bz2(1.38 MB)
    restinio-0.6.8-full.zip(2.52 MB)
    restinio-0.6.8.tar.bz2(477.44 KB)
    restinio-0.6.8.zip(870.71 KB)
  • v.0.6.7.1(May 12, 2020)

    New helpers for extraction of parameters for Bearer authentication (thanks to @prince-chrismc):

    #include <restinio/all.hpp>
    #include <restinio/http_field_parser/bearer_auth.hpp>
    ...
    auto on_request(const restinio::request_handle_t & req) {
       using namespace restinio::http_field_parsers::bearer_auth;
       const auto auth_params = try_extract_params(*req,
             restinio::http_field::authorization);
       if(auth_params) { // Parameters successfully extracted.
          if(is_valid_user(auth_params->client_id, auth_params->client_secret)) {
             ...
          }
       }
       ...
    }
    
    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.7.1-full.tar.bz2(1.38 MB)
    restinio-0.6.7.1-full.zip(2.52 MB)
    restinio-0.6.7.1.tar.bz2(475.91 KB)
    restinio-0.6.7.1.zip(869.71 KB)
  • v.0.6.7(May 11, 2020)

    New configuration options for CMake-based builds: RESTINIO_USE_EXTERNAL_EXPECTED_LITE, RESTINIO_USE_EXTERNAL_OPTIONAL_LITE, RESTINIO_USE_EXTERNAL_STRING_VIEW_LITE, RESTINIO_USE_EXTERNAL_VARIANT_LITE.

    New helper function run_async that allows to run an instance of RESTinio's server on a separate thread-pool or thread:

    int main() {
       auto server = restinio::run_async(
          // Asio's io_context to be used.
          // HTTP-server will use own Asio's io_context object.
          restinio::own_io_context(),
          // The settings for the HTTP-server.
          restinio::server_settings_t{}
             .address("127.0.0.1")
             .port(8080)
             .request_handler(...),
          // The size of thread-pool for the HTTP-server.
          16);
       // If we are here and run_async doesn't throw then HTTP-server
       // is started.
    
       ... // Some other actions.
    
       // No need to stop HTTP-server manually. It will be automatically
       // stopped in the destructor of `server` object.
    }
    

    New helpers for working with HTTP-fields like Authorization and Proxy-Authorization, and helpers for the extraction of parameters for Basic authentication:

    #include <restinio/all.hpp>
    #include <restinio/http_field_parser/basic_auth.hpp>
    ...
    auto on_request(const restinio::request_handle_t & req) {
       using namespace restinio::http_field_parsers::basic_auth;
       const auto auth_params = try_extract_params(*req,
             restinio::http_field::authorization);
       if(auth_params) { // Parameters successfully extracted.
          if(is_valid_user(auth_params->username, auth_params->password)) {
             ...
          }
       }
       ...
    }
    

    Some bug fixes.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.7-full.tar.bz2(1.36 MB)
    restinio-0.6.7-full.zip(2.49 MB)
    restinio-0.6.7.tar.bz2(474.76 KB)
    restinio-0.6.7.zip(862.81 KB)
  • v.0.6.6(Apr 13, 2020)

    An experimental type-safe request-router that can be used as a type-safe alternative of express-like router with additional compile-time checking. That new easy_parser_router allows to write:

    namespace epr = restinio::router::easy_parser_router;
    router->http_get(
       epr::path_to_params("/api/v1/posts/",
          epr::non_negative_decimal_number_p<std::uint64_t>(),
          "/revisions/",
          epr::non_negative_decimal_number_p<std::int16_t>()),
       [](const auto & req, std::uint64_t post_id, std::int16_t rev_id) {...});
    

    instead of:

    router->http_get("/api/v1/posts/:post_id(\d{1,10})/revisions/:rev_id(\d{1,5})",
       [](const auto & req, const auto & params) {
          const auto post_id = restinio::cast_to<std::uint64_t>(params["post_id"]);
          const auto rev_id = restinio::cast_to<std::int16_t>(params["rev_id"]);
       });
    

    More information about the new router can be found here.


    An ability to specify a request handler for several HTTP-methods (see #82 for a motivation). It's possible now to write routes like:

    router->add_handler(
       restinio::router::any_of_methods(
          restinio::http_method_lock(), restinio::http_method_unlock()),
       "/api/v1/resources/:rid",
       [](const auto & req, const auto & params) {...});
    
    router->add_handler(
       restinio::router::none_of_methods(
          restinio::http_method_get(), restinio::http_method_post(), restinio::http_method_delete()),
       "/api/v1/users/:user",
       [](const auto & req, const auto & params) {...});
    

    Those new method matchers can be used for express-like or easy_parser-based routers.

    More information about method matchers is here.


    New RESTINIO_FMT_HEADER_ONLY CMake option added. It allows to use the compiled version of fmtlib with RESTinio. Thanks for @prince-chrismc for a patch.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.6-full.tar.bz2(1.35 MB)
    restinio-0.6.6-full.zip(2.48 MB)
    restinio-0.6.6.tar.bz2(468.81 KB)
    restinio-0.6.6.zip(850.11 KB)
  • v.0.6.5(Feb 25, 2020)

    Set of symbols supported by restinio::parse_query_traits::javascript_compatible is extended (#76).

    Addition of restinio::parse_query_traits::x_www_form_urlencoded, restinio::parse_query_traits::relaxed trais.

    Introduction of try_parse_query function.

    Some functions that work with query-string and URI (like parse_query, try_parse_query) now do basic control of the validity of UTF-8 sequences represented as percent-encoded characters.

    New RESTINIO_USE_EXTERNAL_HTTP_PARSER option for CMake-based builds.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.5-full.tar.bz2(1.32 MB)
    restinio-0.6.5-full.zip(2.45 MB)
    restinio-0.6.5.tar.bz2(455.82 KB)
    restinio-0.6.5.zip(816.15 KB)
  • v.0.6.3.1(Feb 7, 2020)

  • v.0.6.3(Jan 31, 2020)

  • v.0.6.2(Dec 12, 2019)

  • v.0.6.1(Nov 13, 2019)

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.1-full.tar.bz2(1.27 MB)
    restinio-0.6.1-full.zip(2.32 MB)
    restinio-0.6.1.tar.bz2(437.77 KB)
    restinio-0.6.1.zip(763.05 KB)
  • v.0.6.0(Aug 29, 2019)

    • API for connection state listeners changed. NOTE. This is a breaking change!
    • Connection state listener has access to TLS-related params for TLS-connections.
    • Some methods/functions now use [[nodiscard]] if it supported by C++ compiler.
    • Macros RESTINIO_VERSION, RESTINIO_VERSION_MAJOR, RESTINIO_VERSION_MINOR, RESTINIO_VERSION_PATCH, RESTINIO_VERSION_MAKE added.
    • Fresh version of externals: Asio 1.14.0 (Asio 1.12 is also supported), optional-lite 3.2.0, variant-lite 1.2.2. Support for fmt 6.0.0 (fmt 5.3.0 is still used by default).

    The documentation for RESTinio v.0.6 can be found here (Developer's Guide) and here (API Reference Manual).

    Please note that since Aug 2019 the development of RESTinio is moved to GitHub. Our old Hg-repositories on BitBucket are abandoned.

    Source code(tar.gz)
    Source code(zip)
    restinio-0.6.0-full.tar.bz2(1.23 MB)
    restinio-0.6.0-full.zip(2.25 MB)
    restinio-0.6.0.tar.bz2(396.28 KB)
    restinio-0.6.0.zip(691.05 KB)
Owner
Stiffstream
We create and support OpenSource-tools to make C++ development easier
Stiffstream
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution

CppServer Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and

Ivan Shynkarenka 867 Aug 8, 2022
Pushpin is a reverse proxy server written in C++ that makes it easy to implement WebSocket, HTTP streaming, and HTTP long-polling services.

Pushpin is a reverse proxy server written in C++ that makes it easy to implement WebSocket, HTTP streaming, and HTTP long-polling services. The project is unique among realtime push solutions in that it is designed to address the needs of API creators. Pushpin is transparent to clients and integrates easily into an API stack.

Fanout 3.1k Aug 4, 2022
Small and fast cross-platform networking library, with support for messaging, IPv6, HTTP, SSL and WebSocket.

frnetlib Frnetlib, is a cross-platform, small and fast networking library written in C++. There are no library dependencies (unless you want to use SS

Fred Nicolson 22 May 16, 2022
Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket, MQTT built-in protocols, async DNS resolver, and non-blocking API.

Mongoose - Embedded Web Server / Embedded Networking Library Mongoose is a networking library for C/C++. It implements event-driven non-blocking APIs

Cesanta Software 8.6k Aug 8, 2022
cuehttp is a modern c++ middleware framework for http(http/https)/websocket(ws/wss).

cuehttp 简介 cuehttp是一个使用Modern C++(C++17)编写的跨平台、高性能、易用的HTTP/WebSocket框架。基于中间件模式可以方便、高效、优雅的增加功能。cuehttp基于boost.asio开发,使用picohttpparser进行HTTP协议解析。内部依赖了nl

xcyl 26 Jul 21, 2022
BingBing 54 Jul 27, 2022
H2O - the optimized HTTP/1, HTTP/2, HTTP/3 server

H2O - an optimized HTTP server with support for HTTP/1.x, HTTP/2 and HTTP/3 (experimental) Copyright (c) 2014-2019 DeNA Co., Ltd., Kazuho Oku, Tatsuhi

H2O 10.1k Aug 4, 2022
A cross-platform network learning demos. Like high-performance http server

Network-Learn A cross-platform network learning demos (toys). And I try not to use 3rd-party libraries. Welcome to try it out and leave your comments.

Ho 229 23 Jul 6, 2022
websocket and http client and server library, coming with ws, a command line swiss army knife utility

Hello world IXWebSocket is a C++ library for WebSocket client and server development. It has minimal dependencies (no boost), is very simple to use an

Machine Zone, Inc. 329 Aug 8, 2022
A Lightweight and fully asynchronous WebSocket client library based on libev

libuwsc(中文) A Lightweight and fully asynchronous WebSocket client library based on libev for Embedded Linux. And provide Lua-binding. Why should I cho

Jianhui Zhao 284 Jul 7, 2022
A collection of C++ HTTP libraries including an easy to use HTTP server.

Proxygen: Facebook's C++ HTTP Libraries This project comprises the core C++ HTTP abstractions used at Facebook. Internally, it is used as the basis fo

Facebook 7.6k Aug 8, 2022
A simple tcp tunnel on c using sockets Right now it only supports linux systems

A simple tcp tunnel on c using sockets Right now it only supports linux systems build BY MAKE mkdir build make cd build ./tunnel.o <localport> <rem

notaweeb 8 Sep 20, 2021
A C++ async HTTP client library to use in asynchronous applications while communicating with REST services.

libashttp An asynchronous HTTP library using Boost.ASIO as the backend. This project is licensed under: Usage Here is a example usage which is taken f

Tolga Hoşgör 52 Jul 3, 2022
Inter-process communication library to enable allocation between processes/threads and send/receive of allocated regions between producers/consumer processes or threads using this ipc buffer.

This is a relatively simple IPC buffer that allows multiple processes and threads to share a dynamic heap allocator, designate "channels" between processes, and share that memory between producer/consumer pairs on those channels.

RaftLib 7 May 24, 2022
Cross-platform, single .h file HTTP server (Windows, Linux, Mac OS X)

EWS - Single .h File C Embeddable Web Server Latest Version: 1.1.4 released September 9, 2021 Supported platforms: Linux, Mac OS X, Windows License: B

Forrest Heller 76 Jul 27, 2022
HTTP and WebSocket built on Boost.Asio in C++11

HTTP and WebSocket built on Boost.Asio in C++11 Branch Linux/OSX Windows Coverage Documentation Matrix master develop Contents Introduction Appearance

Boost.org 3.5k Aug 10, 2022
Simple embeddable C++11 async tcp,http and websocket serving.

net11 Simple embeddable C++11 async tcp,http and websocket serving. What is it? An easily embeddable C++11 networking library designed to make buildin

Jonas Lund 9 Mar 28, 2020
modern c++(c++17), cross-platform, header-only, easy to use http framework

cinatra--一个高效易用的c++ http框架 English | 中文 目录 使用cinatra常见问题汇总(FAQ) cinatra简介 如何使用 快速示例 性能测试 注意事项 roadmap 联系方式 cinatra简介 cinatra是一个高性能易用的http框架,它是用modern

qicosmos 1.4k Aug 13, 2022
Gromox - Groupware server backend with MAPI/HTTP, RPC/HTTP, IMAP, POP3 and PHP-MAPI support for grommunio

Gromox is the central groupware server component of grommunio. It is capable of serving as a replacement for Microsoft Exchange and compatibles. Conne

grommunio 120 Jul 2, 2022