Generate DH-parameters for the server
masterGenerate Diffie-Hellman parameters required by the server using the following command:
openssl dhparam -out dh2048.pem 2048repository·master·Indexed 23 days ago
https://github.com/stiffstream/restinioA high-performance, asynchronous HTTP/1.1 server framework for C++. RESTinio features Express-style routing, middleware, and built-in support for HTTP transformations such as zlib compression. It supports advanced request handling patterns, including asynchronous chained handlers via fixed_size_chain_t, integration with SObjectizer for offloading processing to worker threads, and Basic Authentication credential extraction using http_field_parsers.
Generate Diffie-Hellman parameters required by the server using the following command:
openssl dhparam -out dh2048.pem 2048To simulate different clients (e.g., Alice and Bob) for TLS testing, generate a key, a request, and a signed certificate for each.
For Alice:
openssl genrsa -out alice.key 2048
openssl req -new -key alice.key -out alice.req
openssl x509 -req -in alice.req -CA ca.cer -CAkey ca.key -set_serial 101 -extensions client -days 3650 -outform PEM -out alice.cerFor Bob:
openssl genrsa -out bob.key 2048
openssl req -new -key bob.key -out bob.req
openssl x509 -req -in bob.req -CA ca.cer -CAkey ca.key -set_serial 101 -extensions client -days 3650 -outform PEM -out bob.cer# Alice
openssl genrsa -out alice.key 2048
openssl req -new -key alice.key -out alice.req
openssl x509 -req -in alice.req -CA ca.cer -CAkey ca.key -set_serial 101 -extensions client -days 3650 -outform PEM -out alice.cer
# Bob
openssl genrsa -out bob.key 2048
openssl req -new -key bob.key -out bob.req
openssl x509 -req -in bob.req -CA ca.cer -CAkey ca.key -set_serial 101 -extensions client -days 3650 -outform PEM -out bob.cerTo set up a private PKI for TLS inspection, first generate a CA key and certificate using OpenSSL:
openssl req -newkey rsa:2048 -keyform PEM -keyout ca.key -x509 -days 3650 -outform PEM -out ca.cerRun the tls_inspector sample by passing the directory containing your certificates as an argument. Ensure you provide a valid path to the CA and server certificates.
./target/release/sample.tls_inspector sample/tls_inspector/certsFollow these steps to create a signed server certificate:
openssl genrsa -out server.key 2048openssl req -new -key server.key -out server.req -sha256openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 100 -extensions server -days 3650 -outform PEM -out server.cer -sha256rm server.reqopenssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.req -sha256
openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 100 -extensions server -days 3650 -outform PEM -out server.cer -sha256
rm server.reqWebSocket connections in RESTinio can be managed through the rws::ws_handle_t:
wsh->send_message(*m) followed by wsh->shutdown().wsh->kill().wsh->connection_id() to get a unique identifier for the connection, which is useful for tracking connections in a registry.Important: Because WebSocket handles are often managed via shared pointers in user-defined registries, ensure that you remove the handler from your registry when the connection is closed or killed to allow the handler to be destroyed.
// Graceful shutdown
wsh->send_message( *m );
wsh->shutdown();
// Abrupt kill
wsh->kill();RESTinio allows you to attach custom, per-request data structures to every incoming request. This is useful for storing authentication results, user identities, or session information that needs to be accessed by various handlers in a request processing chain.
To implement this:
per_request_data_t).restinio::simple_extra_data_factory_t<T> to create a factory for your type.server_traits_t using the extra_data_factory_t alias.req->extra_data().If you are using the Express router, you must use restinio::router::generic_express_router_t and provide your extra data factory type to ensure the router is compatible with the extra data.
The easy_parser_router_t (found in restinio::router) provides a high-level way to define routes that automatically parse path parameters into specific types. It uses a declarative syntax to map HTTP methods and paths to handler functions.
Key features include:
>> to chain parsers (e.g., parsing a fragment and then unescaping it).none_of_methods to explicitly handle or reject specific HTTP methods for a given path.request_handle_t or the request handle plus the parsed parameters.RESTinio provides a zlib transform facility to handle HTTP content encoding (gzip, deflate, or identity). To use it, you create a body appender using restinio::transforms::zlib::body_appender, which wraps a response object and applies the selected compression algorithm to the data being appended.
Key components:
rtz::make_gzip_compress_params(level): Creates parameters for gzip compression.rtz::make_deflate_compress_params(level): Creates parameters for deflate compression.rtz::make_identity_params(): Creates parameters for no compression (identity).rtz::body_appender(response, params): Returns an appender object used to write data to the response.ba.append(data): Appends a single block of data.ba.make_chunk(data) and ba.flush(): Used with restinio::chunked_output_t to stream data in chunks.ba.complete(): Finalizes the transformation and the response body.You can chain multiple request handlers together by passing them as multiple arguments to the .request_handler() method when configuring the server. This allows you to implement a middleware-like pattern where one handler can decide whether to process a request or delegate it to the next handler in the chain.
To delegate to the next handler, a handler must return restinio::request_not_handled(). If a handler processes the request and wants to stop the chain, it should return restinio::request_accepted().
In the example below, the first handler (create_auth_handler) checks for authentication. If authentication fails, it returns a 401 Unauthorized response and restinio::request_accepted(). If authentication succeeds, it returns restinio::request_not_handled(), allowing the second handler (create_request_handler) to take over.
restinio::run(
restinio::on_this_thread<traits_t>()
.port( 8080 )
.address( "localhost" )
.request_handler(
create_auth_handler(),
create_request_handler() )
);To run a RESTinio server, you must define server traits, instantiate the server with settings, and then use a runner to manage the execution lifecycle.
restinio::default_traits_t. You can specify a logger_t (e.g., restinio::shared_ostream_logger_t).restinio::http_server_t< my_server_traits_t >. The constructor takes an io_context (e.g., restinio::own_io_context()) and a restinio::server_settings_t< my_server_traits_t > object.server_settings_t to set the .port(), .address(), and .request_handler().restinio::on_pool_runner_t< server_t >. Pass the number of threads (e.g., std::thread::hardware_concurrency()) and the server instance to the runner, then call .start().runner.stop() and then runner.wait() to ensure a clean shutdown.struct my_server_traits_t : public restinio::default_traits_t
{
using logger_t = restinio::shared_ostream_logger_t;
};
using server_t = restinio::http_server_t< my_server_traits_t %>;
server_t server{
restinio::own_io_context(),
restinio::server_settings_t< my_server_traits_t >{}
.port( 8080 )
.address( "localhost" )
.request_handler( handler )
};
// Run server on a separate thread_pool.
restinio::on_pool_runner_t< server_t > runner{
std::thread::hardware_concurrency(),
server
};
runner.start();
// To stop:
// runner.stop();
// runner.wait();To enable TLS, you must provide an SSL context (compatible with asio::ssl::context) and register it with the server configuration.
asio_ns::ssl::context (where asio_ns is restinio::asio_ns).restinio::asio::ssl::verify_peer)..tls_context(std::move(tls_context)).Example configuration:
namespace asio_ns = restinio::asio_ns;
auto tls_context = asio_ns::ssl::context{ asio_ns::ssl::context::sslv23 };
tls_context.use_certificate_chain_file("server.cer");
tls_context.use_private_key_file("server.key", asio_ns::ssl::context::pem);
tls_context.set_verify_mode(asio_ns::ssl::verify_peer | asio_ns::ssl::verify_fail_if_no_peer_cert);asio_ns::ssl::context tls_context{ asio_ns::ssl::context::sslv23 };
tls_context.set_options(
asio_ns::ssl::context::default_workarounds
| asio_ns::ssl::context::no_sslv2
| asio_ns::ssl::context::single_dh_use );
tls_context.use_certificate_chain_file( certs_dir + "/server.cer" );
tls_context.use_private_key_file(
certs_dir + "/server.key",
asio_ns::ssl::context::pem );
tls_context.set_verify_mode(
asio_ns::ssl::verify_peer
| asio_ns::ssl::verify_fail_if_no_peer_cert );
tls_context.load_verify_file( certs_dir + "/ca.cer" );
tls_context.use_tmp_dh_file( certs_dir + "/dh2048.pem" );