BeastHttp icon indicating copy to clipboard operation
BeastHttp copied to clipboard

add possibility of using middlewares with `use`, not only in http methods

Open gocarlos opened this issue 6 years ago • 4 comments

middlewares are great to check for credentials and permissions e.g. authentication and authorization.

  auto authMiddleware = [](HttpRequest request, HttpContext context, auto iterator) {
    if (request[boost::beast::http::field::authorization] != "my_token") {
      context.send(make_401<boost::beast::http::string_body>(request));
    } else {
      std::next(iterator)();
    }
  };

  const std::string route_base{R"(^/$)"};
  http::basic_router<HttpSession> main_router{std::regex::ECMAScript};

  const std::string route_api{R"(^/api/v0)"};
  http::basic_router<HttpSession> api_router{std::regex::ECMAScript};

  api_router.get("^[/]??$", [](auto request, auto context) {
    context.send(make_200<boost::beast::http::string_body>(request, R"({"status": "ok"})"));
  });

  // this does work
  api_router.get("^/asdf$",
                 std::bind(authMiddleware, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
                 [](auto request, auto context) {
                   context.send(make_200<boost::beast::http::string_body>(request, R"({"status": "ok"})"));
                 });

  // this does not work
  main_router.use(route_api, authMiddleware, api_router);

basically all routes would need authentication, instead of adding a middleware to all http methods

gocarlos avatar Sep 20 '19 08:09 gocarlos

my first guess was to add the missing template to basic_router.cpp though no luck -> does not work either (compiling though now functioning):

    template <class... OnRequest>
    void use(resource_regex_type const& path_to_resource, const base_type& other, OnRequest&&... on_request) {
      add_resource_cb_without_method(path_to_resource, storage_type{std::forward<OnRequest>(on_request)...});

      base_type::use(path_to_resource, other);
    }
  main_router.use(route_api_str, api_router, [](auto request, auto context) {
    if (request[boost::beast::http::field::authorization] != "my_token") {
      context.send(make_401<boost::beast::http::string_body>(request));
      std::cout << "asdf" << std::endl;
      return;
    }
  });

gocarlos avatar Sep 20 '19 12:09 gocarlos

If you still need to, but why not do this:

  api_router.get("^/1$",
                 std::bind(authMiddleware, std::_1, std::_2, std::_3),
                 [](auto request, auto context) {
                   /// ...
                 });

  api_router.get("^/2$",
                 std::bind(authMiddleware, std::_1, std::_2, std::_3),
                 [](auto request, auto context) {
                   /// ...
                 });
// ...

main_router.use("/numbers", api_router);

?

0xdead4ead avatar Sep 28 '19 18:09 0xdead4ead

The point is that it does not seem to work to use chainable middlewares for e.g. logging, authentication etc for router.use one can use the middlewares only wity router.get|post|put etc

Using an auth middleware in all get methods is pretty verbose when you can just add one middleware to the router... E.g. all routes starting with /api/ shall be authenticated with e.g. a token And all other routes are serving static content which is public Furthermore all routes with /api/admin/ shall be send through an authorization middleware after the authentication middleware

gocarlos avatar Sep 28 '19 19:09 gocarlos

did it myself as I also needed other features... Example of what I wished in this issue: https://github.com/expresscpp/expresscpp/blob/master/example/router.cpp

gocarlos avatar Nov 20 '19 19:11 gocarlos