BeastHttp
BeastHttp copied to clipboard
add possibility of using middlewares with `use`, not only in http methods
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
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;
}
});
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);
?
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
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