Library / SDK
Stiffstream/restinio avatar
Stiffstream/restinio

RESTinio: an embedded HTTP and WebSocket server for C++

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

1,311 stars118 forksC++NOASSERTION

At a glance

What is it?
RESTinio is a C++17 library that gives an application an embedded HTTP and WebSocket server, built on standalone ASIO with Boost::ASIO also supported. It is header-only apart from its HTTP parser dependency, and the interesting part of its design is that the request handling and the execution context are separate, so a handler can be handed to another thread and answered later.
Who is it for?
Adopt RESTinio if you are writing a C++ service that needs an HTTP or WebSocket endpoint without taking on a full application framework, and you are comfortable with the ASIO programming model. Do not adopt it if your team is more productive in a higher-level stack, because everything here is expressed in the type system of C++ templates.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 66 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • Stiffstream/restinio1,311 ★ · +4
Star history
Repository2026-10-202026-11-07
Stiffstream/restinio1.3k1.3k

4 Stars in the last 18 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

A server you link into your own program

RESTinio is a C++17 library that gives you an embedded HTTP and WebSocket server. It is based on the standalone version of ASIO and is targeted primarily for asynchronous processing of HTTP requests, and Boost::ASIO is also supported.

The last point is worth pausing on. The standalone ASIO distribution is header-only and dependency-free, which means a project can use it without pulling in Boost, which is a large dependency to take on for the sake of an event loop. The Boost path exists for projects that already have Boost, and the choice is the consumer's.

RESTinio itself is a header-only library, but it depends on the nodejs/llhttp HTTP parser, which is not header-only. That is a real constraint on the word header-only, and it is stated up front rather than discovered at link time. The repository carries the licence files for the pieces it bundles, with LICENSE.catch2, LICENSE.expected-lite, LICENSE.fmtlib, LICENSE.llhttp and LICENSE.zlib alongside the project's own.

The project's own statement about its maturity is worth quoting. It says RESTinio is currently in a rather stable state and that since v0.4.0 it is ready for production use. The phrasing is cautious rather than boastful, which is a reasonable tone for a library that has been in that state for a long time.

The licence is BSD-3-CLAUSE, the primary language is C++, and the last push was on 2026-09-03.

A very basic example

The README leads with the task of writing a C++ application that must support some REST API, and then with the simplest possible case.

C++
#include <restinio/core.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;
}

That is the whole API in six lines. The server runs on the main thread and responds to all requests with the hello-world message, and the request handler is a lambda that takes the request handle and returns a response.

The one type that matters is the request handle, and the README points at it in the next sentence. Of course you have access to the structure of a given HTTP request, so you can apply a complex logic for handling requests.

The response is built through the handle as well, with create_response() giving a builder, set_body setting the body and done() finalising it. Everything in the library hangs off those two objects, which is why the hello-world example is genuinely the whole mental model rather than a simplification of a more complicated one.

What the feature list actually covers

The features list is longer than most, and a few items are more revealing than they look.

Async request handling is the first. If you cannot get the response data immediately, that is fine, store the request handle somewhere or pass it to another execution context and get back to it when the data is ready. That is the architectural centre of the library, and the reason the response is built from the handle rather than returned as a value.

HTTP pipelining works well with async request handling and might increase your server throughput dramatically. Timeout control means RESTinio can take care of bad connections, described as ones that send GET / and then just get stuck, which is the kind of resource leak that a hand-rolled server has to handle separately.

On the API side there are response builders, including a special one for a chunked-encoded body, an ExpressJS-like request routing, and an experimental typesafe request router that avoids the problems of the ExpressJS-like router with the help of static checks from the C++ compiler. You can chain several request handlers, somewhat similar to ExpressJS's middleware. There is support for query string parameters, several ready-to-use helpers for working with HTTP headers, including the support for file uploading headers, and support for sending files and their parts, with sendfile on Linux and Unix and TransmitFile on Windows.

The rest is compression with deflate and gzip, TLS for HTTPS, basic WebSocket support, tune options for acceptor and socket settings, and the ability to accept connections in parallel when running on a pool of threads.

The express router, with regex parameters

The enhanced example shows the router, and the interesting part is the route pattern.

C++
    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();
            });

The route is a pattern with a named parameter and a regular expression constraint, written as :meter_id with a digit group. The handler receives the request and the extracted parameters as a map, and the query string is parsed separately with parse_query on the request header, then read with opt_value for the parts that might be missing.

The example also shows the non-matched request handler, which returns a not found status and closes the connection, and the server traits, where a struct derives from default_single_thread_traits_t and sets the request handler type to the router, which is how the router is installed into the server.

That last piece is the mechanism for choosing a router, and it is worth understanding because the ExpressJS-like router is one option among the traits you can select.

The execution context is separate from the library

Two features in the list determine how the server behaves in a real application.

The first is that RESTinio can run on an external asio::io_context, and the README states that RESTinio is separated from the execution context. That is the difference between a library that owns its threads and one that fits into an event loop you already have. If your application runs an io_context for its own reasons, the server can be a service on it rather than a thing that starts its own world.

The second is the threading model. The run and on_this_thread calls in the examples put the server on the calling thread, and the tune options let you set acceptor and socket options, and when running RESTinio on a pool of threads, connections can be accepted in parallel.

Combining the two gives the practical shape of a deployment. One thread accepts connections, the work is handed off, and a handler that needs to wait on a database or a remote call can park the request handle and resume it later, which is exactly the async request handling the first feature describes.

The timeout control belongs in that picture too. A server that accepts connections in parallel and hands work to other execution contexts needs a policy for a client that connects and never says anything, and RESTinio handles that case itself, so you do not have to write a watchdog per connection.

WebSocket support, licences and where the documentation lives

The WebSocket support is described as basic, and the mechanism is one call. You simply call restinio::websocket::basic::upgrade() on the request handle and start a WebSocket session on the corresponding connection. The word basic is doing some work in that sentence, since it suggests the implementation covers the upgrade and the session rather than the full range of WebSocket features.

On licensing, RESTinio is distributed under the BSD-3-CLAUSE licence, and the repository root holds the licence files for the dependencies it vendors, with separate files for Catch2, expected-lite, the fmt library, llhttp and zlib. That last group is the one to look at, because a bundled dependency brings its own obligations, and the project is explicit enough to keep each licence next to the code.

The full documentation is at the Stiffstream site, at the docs path for the 0.7 line, so the version in the URL is the version the documentation describes.

For questions there are three places. Bugs go to the issue tracker on GitHub, the discussions section on GitHub is for discussion, and there is a Google Group named restinio for the older style of thread.

The repository itself carries a mix of Mercurial and Git artefacts, with a .hgignore and .hgtags alongside the .gitattributes and .gitignore, which means the history was converted from Mercurial at some point. The dev/ directory is where the development tooling lives, and externals.rb is the build file for the vendored externals.

Editorial conclusion

Adopt RESTinio if you are writing a C++ service that needs an HTTP or WebSocket endpoint without taking on a full application framework, and you are comfortable with the ASIO programming model. Do not adopt it if your team is more productive in a higher-level stack, because everything here is expressed in the type system of C++ templates. Before you start, read the feature list against what you actually need, since the timeout and pipelining behaviour is where the difference from a simple server shows, and check the licensing, since RESTinio is BSD-3-Clause while the bundled dependencies carry their own files in the repository.

Frequently asked questions

What is RESTinio?

It is a C++17 library that gives you an embedded HTTP and WebSocket server, based on the standalone version of ASIO and aimed at asynchronous processing of HTTP requests, with Boost::ASIO also supported. The project says it has been in a rather stable state and has been ready for production use since v0.4.0.

Is RESTinio really header-only?

Almost. RESTinio itself is a header-only library, but it depends on the nodejs/llhttp HTTP parser, which is not header-only. The repository also carries licence files for the bundled dependencies, including Catch2, expected-lite, the fmt library, llhttp and zlib.

How does asynchronous request handling work in RESTinio?

If you cannot get the response data immediately, you store the request handle somewhere or pass it to another execution context and get back to it when the data is ready. The response is then built from that handle with create_response(), and RESTinio can also run on an external asio::io_context, which keeps it separate from the execution context.

What are the notable RESTinio features?

Async request handling, HTTP pipelining, timeout control for connections that stall, response builders including a chunked-encoded body builder, ExpressJS-like routing and an experimental typesafe router with compiler checks, handler chaining like middleware, query string support, header helpers including file upload, file sending with sendfile on Linux and TransmitFile on Windows, deflate and gzip compression, TLS, basic WebSocket support through restinio::websocket::basic::upgrade(), and acceptor and socket tuning options.

What licence is RESTinio under and how is it maintained?

RESTinio is distributed under the BSD-3-CLAUSE licence, with the full documentation on the Stiffstream site for the 0.7 line. The recent releases are v0.7.9 on 2026-01-07, v0.7.9.1 on 2026-04-02 and v0.7.10 on 2026-09-03, with the last push on the same day as the newest tag.

Official sources

  1. Issues
  2. README
  3. Releases
  4. Stiffstream/restinio on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stiffstream-restinio.svg)](https://hysenlabs.com/projects/stiffstream-restinio)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/stiffstream-restinio.svg)](https://hysenlabs.com/projects/stiffstream-restinio)

Was this useful?