RESTinio-0.6.13: The last big RESTinio release in 2020 and probably the last in the 0.6 branch







RESTinio is a relatively small C ++ 14 library for embedding an HTTP / WebSocket server in C ++ applications. We have tried to make RESTinio easy to use, highly customizable, with decent performance. And, it seems, so far it turns out.







Previously, there were already articles about RESTinio , but they were more about what and how was done in the giblets of the library. Today I would like to talk about what appeared in the fresh version of RESTinio, and why it appeared. And also say a few words about why this release is likely to be the last big update within the 0.6 branch. And what I would like to achieve when working on the 0.7 branch.







Anyone interested, you are welcome under cat.







Main feature of version 0.6.13: chains of synchronous handlers



, 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 . 0.6.13 . ?







.







, 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 ?







. , RESTinio- request_t



.







.







/, -:







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>



.







easy_parser_router:







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 .







A significant role in this was played by our users, who risked choosing RESTinio for their tasks. And someone also found the time / opportunity for feedback. Thanks to this, RESTinio was able to get rid of several shortcomings and provide several features.







So I want to say a big thank you to everyone interested in RESTinio. Your attention is very important to us.







And, of course, a huge thanks to everyone using RESTinio. Without you, this project would not have developed.







Well, Happy New Year!








All Articles