Stiffstream / restinio

Cross-platform, efficient, customizable, and robust asynchronous HTTP(S)/WebSocket server C++ library with the right balance between performance and ease of use
Other
1.15k stars 93 forks source link

Request Interceptor #17

Closed webfolderio closed 5 years ago

webfolderio commented 5 years ago

Hi,

Is there a filter feature to intercept all request? I am going to implement generic JWT authentication and metrics handler but couldn't figure out the optimal solution.

Thanks

eao197 commented 5 years ago

Hi!

Sorry for the delay with the response, I needed some time to think.

I suppose you want to implement some handler that will accept all incoming requests, do something and then delegate the processing of a request to ordinary RESTinio mechanisms (like express-router).

If so then I'm afraid the only way to do that is to write your own router object. This object will accept all requests, do what you need and then will call some of RESTinio's standard router. For example, it could be something like that:

class interceptor_router {
    // This will be the actual router.
   restinio::router::express_router_t actual_router_;
   ...
public:
   // Add a request handler to actual_router.
   void http_get(restinio::string_view_t path, restinio::router::express_request_handler_t handler) {
      actual_router_.http_get(path, std::move(handler));
   }
   void http_post(restinio::string_view_t path, restinio::router::express_request_handler_t handler) {
      actual_router_.http_post(path, std::move(handler));
   }
   ...
   // This operator will be called by RESTinio on arrival of a new request.
   restinio::request_handling_status_t operator()(restinio::request_handle_t req) const
   {
      ... // Do what you want.
      // Now the actual router can be called.
      actual_handler_(std::move(req));
   }
   ...
};

Then you can parametrize RESTinio's server traits by this type:

struct my_traits_t : public restinio::default_traits_t {
   using request_handler_t = interceptor_router;
};
...
run( restinio::on_thread_pool<my_traits_t>(4)... );

PS. It seems that you can derive interceptor_router from restinio::router::express_router_t:

class interceptor_router : public restinio::router::express_router_t {
   using base_type = restinio::router::express_router_t;
   ...
public:
   // This operator will be called by RESTinio on arrival of a new request.
   restinio::request_handling_status_t operator()(restinio::request_handle_t req) const
   {
      ... // Do what you want.
      // Now the actual router can be called.
      base_type::operator()(std::move(req));
   }
   ...
};

In that case you don't need to redefine methods like http_get and http_put in your router type.

webfolderio commented 5 years ago

Thanks so much, your code snippet it works flawlessly.