
RESTinio es una biblioteca C ++ 14 relativamente pequeña para incrustar un servidor HTTP / WebSocket en aplicaciones C ++. Hemos tratado de hacer que RESTinio sea fácil de usar, altamente personalizable y con un rendimiento decente. Y, al parecer, hasta ahora resulta.
Anteriormente, ya había artículos sobre RESTinio , pero eran más sobre qué y cómo se hacía en las menudencias de la biblioteca. Hoy me gustaría hablar sobre lo que apareció en la nueva versión de RESTinio y por qué apareció. Y también diga algunas palabras sobre por qué es probable que esta versión sea la última gran actualización dentro de la rama 0.6. Y lo que me gustaría lograr al trabajar en la rama 0.7.
Cualquiera que esté interesado, es bienvenido bajo gato.
Característica principal de la versión 0.6.13: cadenas de controladores síncronos
, 2017- RESTinio, HTTP- C++ . , . , RESTinio ExpressJS. express_router RESTinio.
ExpressJS : middleware. - RESTinio .
. RESTinio , - middleware ExpressJS . , middleware RESTinio.
, . .
, 0.6.13 RESTinio . . not_handled
. - accepted
rejected
, .
, , :
- - ;
- HTTP-;
- ( ) , .
:
auto incoming_req_logger(const restinio::request_handle_t & req)
{
... // .
// .
return restinio::request_not_handled();
}
auto mandatory_fields_checker(const restinio::request_handle_t & req)
{
... // .
if(!ok) {
// .
return req->create_response(restinio::status_bad_request())
...
.done(); // accepted.
}
// .
return restinio::request_not_handled();
}
auto permissions_checker(const restinio::request_handle_t & req)
{
... // .
if(!ok) {
// .
return req->create_response(restinio::status_unauthorized())
...
.done(); // accepted.
}
// .
return restinio::request_not_handled();
}
auto actual_processor(const restinio::request_handle_t & req)
{
... // .
return restinio::request_accepted();
}
, .
-, . RESTinio , .
, , fixed_size_chain_t
:
// .
#include <restinio/sync_chain/fixed_size.hpp>
...
struct my_traits : public restinio::default_traits_t {
using request_handler_t = restinio::sync_chain::fixed_size_chain_t<4>;
};
-, :
restinio::run(restinio::on_this_thread<my_traits>()
.port(...)
.address(...)
.request_handler(
// .
incoming_req_logger,
mandatory_fields_checker,
permissions_checker,
actual_processor)
...
);
, , .
?
.
, RESTinio .
, , , RESTinio . RESTinio : , , , , , , -...
, RESTinio , , , , . - RESTinio . , RESTinio . RESTinio, , , : rejected
accepted
.
, . (.. create_response()...done()
) . - , - done()
.
, , accepted
, RESTinio , . - . , - .
RESTinio accepted
, . RESTinio , .
.
RESTinio . , fixed_size_chain_t
— , RESTinio. . RESTinio , RESTinio .
, not_handled
, rejected
, accepted
. ?
. , - .
. .. , - .
- 0.6.13 . .. , . , RESTinio, , - - . , . , , RESTinio.
, - ?
. - . accepted
.
?
, . . 0.6.13 0.6 . , API RESTinio.
. .
, :
- authentification_handler, ;
- permissions_checker, , ;
- admin_access_logger, ;
- actual_processor, .
user_permissions, . permissions_checker- ( ) admin_access_logger ( ).
, , authentification_handler ?
.
/, -:
struct user_permissions {...};
...
// .
struct per_request_data {
user_permissions user_info_;
... // , - .
};
.. extra-data-factory, .. :
struct my_extra_data_factory {
// extra-data-factory data_t.
using data_t = per_request_data;
// .
void make_within(restinio::extra_data_buffer_t<data_t> buf) {
new(buf.get()) data_t{};
}
};
:
struct my_traits : public restinio::default_traits_t {
using extra_data_factory_t = my_extra_data_factory;
};
, , : . restinio::request_handle_t
restinio::generic_request_handle_t<per_request_data>
:
restinio::request_handling_status_t authentification_handler(
const restinio::generic_request_handle_t<per_request_data> & req);
restinio::request_handling_status_t permissions_checker(
const restinio::generic_request_handle_t<per_request_data> & req);
restinio::request_handling_status_t admin_access_logger(
const restinio::generic_request_handle_t<per_request_data> & req);
restinio::request_handling_status_t actual_processor(
const restinio::generic_request_handle_t<per_request_data> & req);
, .
DefaultConstructible , — . stateful-, , . :
// .
struct per_request_data {
std::shared_ptr<log_stream> log_;
per_request_data(std::shared_ptr<log_stream> log)
: log_{std::move(log)}
{}
};
// .
class my_extra_data_factory {
std::shared_ptr<logger> logger_;
public:
using data_t = per_request_data;
my_extra_data_factory(std::shared_ptr<logger> logger)
: logger_{std::move(logger)}
{}
void make_within(restinio::extra_data_buffer_t<data_t> buf) {
new(buf.get()) data_t{
std::make_shared<log_stream>(logger_)
};
}
};
struct my_traits : public restinio::default_traits_t {
using extra_data_factory_t = my_user_data_factory;
};
auto logger = std::make_shared<logger>(...);
// .
restinio::run(restinio::on_thread_pool<my_traits>(16)
.port(...)
.address(...)
// RESTinio.
.extra_data_factory(std::make_shared<my_user_data_factory>(logger))
.request_handler(...)
);
extra_data
generic_request_t
:
restinio::request_handling_status_t authentification_handler(
const restinio::generic_request_handle_t<per_request_data> & req)
{
... // .
if(!ok) {
// .
return req->create_response(...)...done();
}
else {
// .
req->extra_data().user_info_ = user_permissions{...};
return restinio::request_not_handled();
}
}
restinio::request_handling_status_t permissions_checker(
const restinio::generic_request_handle_t<per_request_data> & req)
{
// .
const auto & user_info = req->extra_data().user_info_;
... // .
}
, generic_request_t<Extra_Data>
, 0.6.13, RESTinio : generic_request_t<Extra_Data>
generic_request_handle_t<Extra_Data>
( std::shared_ptr<generic_request_t<Extra_Data>>
).
, , request_t
request_handle_t
generic_request_t<no_extra_data_factory_t::data_t>
generic_request_handle_t<no_extra_data_factory_t::data_t>
, no_extra_data_factory_t
— .
restinio::traits_t
, restinio::default_traits_t
restinio::default_single_thread_traits_t
no_extra_data_factory_t
extra_data_factory_t
. , request_t
request_handle_t
, .
extra-data express-/easy_parser_router
, express_router, ExpressJS, RESTinio. express_router . , extra-data express_router-.
extra-data , express_router-, express_router- extra-data. :
struct my_extra_data_factory { ... };
struct my_traits : public restinio::default_traits_t {
using extra_data_factory_t = my_extra_data_factory;
using request_handler_t = restinio::router::express_router_t<
restinio::router::std_regex_engine_t,
extra_data_factory_t>;
};
express_router request_handle_t
generic_request_handle_t<my_traits::extra_data_factory_t::data_t>
.
struct my_traits : public restinio::default_traits_t {
using extra_data_factory_t = my_extra_data_factory;
using request_handler_t = restinio::router::easy_parser_router_t<
extra_data_factory_t>;
};
RESTinio-0.7?
, 0.6 0.7.
.
-, RESTinio http-parser. , , . , http-parser ( ), RESTinio. , .
-, RESTinio , . , . , - . ?
-, , , , 0.6 . :
- http/1.1, http/2, http/3;
- , RESTinio , ;
- .
, , 0.6 .
- RESTinio?
RESTinio, , RESTinio.
, , .
, RESTinio . :( ;)
, , RESTinio, Issues Discussions GitHub. Google-. , .
2020- . , , . , RESTinio . , RESTinio .
Nuestros usuarios jugaron un papel importante en esto, quienes se arriesgaron a elegir RESTinio para sus tareas. Y alguien también encontró el tiempo / la oportunidad para recibir comentarios. Gracias a esto, RESTinio pudo deshacerse de varias deficiencias y proporcionar varias características.
Por eso quiero dar las gracias a todos los interesados en RESTinio. Tu atención es muy importante para nosotros.
Y, por supuesto, muchas gracias a todos los que utilizan RESTinio. Sin ti, este proyecto no se habría desarrollado.
¡Feliz año nuevo!