diff options
author | Ed Tanous <edtanous@google.com> | 2023-02-10 05:08:23 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2023-04-27 20:18:35 +0300 |
commit | 15a42df05b033a06e38d2998511d6c79d09d66a7 (patch) | |
tree | 9e21eba54b9d5783a5d233c69a345d9bb964123d /http/routing.hpp | |
parent | 02e01b5108d46720a0b438c0d79952464320d954 (diff) | |
download | bmcweb-15a42df05b033a06e38d2998511d6c79d09d66a7.tar.xz |
Remove number support from the router
The router historically came from crow. Crow supported wildcards of
<int>, <float>, and <double>. bmcweb doesn't use them, nor should it in
basically any case, as we now have explicit 404 handling.
This commit removes them. This amounts to about -450 lines of code, but
it's some of the scarier code we have, some of it existing in the
namespace "black_magic". Reducing the brain debt for people working in
this subsystem seems worthwhile. There is no case in the future where
we would use integer based url parameters.
Tested: Redfish service validator passes. Should be good enough
coverage for a code removal.
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I34add8df7d3486952474ca7ec3dc6be990c50ed0
Diffstat (limited to 'http/routing.hpp')
-rw-r--r-- | http/routing.hpp | 296 |
1 files changed, 49 insertions, 247 deletions
diff --git a/http/routing.hpp b/http/routing.hpp index 0059760abe..e73297c3e4 100644 --- a/http/routing.hpp +++ b/http/routing.hpp @@ -56,7 +56,7 @@ class BaseRule virtual void handle(const Request& /*req*/, const std::shared_ptr<bmcweb::AsyncResp>&, - const RoutingParams&) = 0; + const std::vector<std::string>&) = 0; #ifndef BMCWEB_ENABLE_SSL virtual void handleUpgrade(const Request& /*req*/, @@ -131,82 +131,34 @@ template <typename H1> struct CallParams { H1& handler; - const RoutingParams& params; + const std::vector<std::string>& params; const Request& req; const std::shared_ptr<bmcweb::AsyncResp>& asyncResp; }; -template <typename F, int NInt, int NUint, int NDouble, int NString, - typename S1, typename S2> +template <typename F, int NString, typename S1, typename S2> struct Call {}; -template <typename F, int NInt, int NUint, int NDouble, int NString, - typename... Args1, typename... Args2> -struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<int64_t, Args1...>, +template <typename F, int NString, typename... Args1, typename... Args2> +struct Call<F, NString, black_magic::S<std::string, Args1...>, black_magic::S<Args2...>> { void operator()(F cparams) { using pushed = typename black_magic::S<Args2...>::template push_back< - CallPair<int64_t, NInt>>; - Call<F, NInt + 1, NUint, NDouble, NString, black_magic::S<Args1...>, - pushed>()(cparams); - } -}; - -template <typename F, int NInt, int NUint, int NDouble, int NString, - typename... Args1, typename... Args2> -struct Call<F, NInt, NUint, NDouble, NString, - black_magic::S<uint64_t, Args1...>, black_magic::S<Args2...>> -{ - void operator()(F cparams) - { - using pushed = typename black_magic::S<Args2...>::template push_back< - CallPair<uint64_t, NUint>>; - Call<F, NInt, NUint + 1, NDouble, NString, black_magic::S<Args1...>, - pushed>()(cparams); - } -}; - -template <typename F, int NInt, int NUint, int NDouble, int NString, - typename... Args1, typename... Args2> -struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<double, Args1...>, - black_magic::S<Args2...>> -{ - void operator()(F cparams) - { - using pushed = typename black_magic::S<Args2...>::template push_back< - CallPair<double, NDouble>>; - Call<F, NInt, NUint, NDouble + 1, NString, black_magic::S<Args1...>, - pushed>()(cparams); - } -}; - -template <typename F, int NInt, int NUint, int NDouble, int NString, - typename... Args1, typename... Args2> -struct Call<F, NInt, NUint, NDouble, NString, - black_magic::S<std::string, Args1...>, black_magic::S<Args2...>> -{ - void operator()(F cparams) - { - using pushed = typename black_magic::S<Args2...>::template push_back< CallPair<std::string, NString>>; - Call<F, NInt, NUint, NDouble, NString + 1, black_magic::S<Args1...>, - pushed>()(cparams); + Call<F, NString + 1, black_magic::S<Args1...>, pushed>()(cparams); } }; -template <typename F, int NInt, int NUint, int NDouble, int NString, - typename... Args1> -struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<>, - black_magic::S<Args1...>> +template <typename F, int NString, typename... Args1> +struct Call<F, NString, black_magic::S<>, black_magic::S<Args1...>> { void operator()(F cparams) { - cparams.handler( - cparams.req, cparams.asyncResp, - cparams.params.template get<typename Args1::type>(Args1::pos)...); + cparams.handler(cparams.req, cparams.asyncResp, + cparams.params[Args1::pos]...); } }; @@ -289,8 +241,7 @@ struct Wrapped using type = std::function<void( const crow::Request& /*req*/, const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>; - using args_type = - black_magic::S<typename black_magic::PromoteT<Args>...>; + using args_type = black_magic::S<Args...>; }; template <typename... Args> @@ -299,8 +250,7 @@ struct Wrapped using type = std::function<void( const crow::Request& /*req*/, const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>; - using args_type = - black_magic::S<typename black_magic::PromoteT<Args>...>; + using args_type = black_magic::S<Args...>; }; template <typename... Args> @@ -310,19 +260,18 @@ struct Wrapped using type = std::function<void( const crow::Request& /*req*/, const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>; - using args_type = - black_magic::S<typename black_magic::PromoteT<Args>...>; + using args_type = black_magic::S<Args...>; }; typename HandlerTypeHelper<ArgsWrapped...>::type handler; void operator()(const Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const RoutingParams& params) + const std::vector<std::string>& params) { detail::routing_handler_call_helper::Call< detail::routing_handler_call_helper::CallParams<decltype(handler)>, - 0, 0, 0, 0, typename HandlerTypeHelper<ArgsWrapped...>::args_type, + 0, typename HandlerTypeHelper<ArgsWrapped...>::args_type, black_magic::S<>>()( detail::routing_handler_call_helper::CallParams<decltype(handler)>{ handler, params, req, asyncResp}); @@ -344,7 +293,7 @@ class WebSocketRule : public BaseRule void handle(const Request& /*req*/, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const RoutingParams& /*params*/) override + const std::vector<std::string>& /*params*/) override { asyncResp->res.result(boost::beast::http::status::not_found); } @@ -526,7 +475,7 @@ class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> void handle(const Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const RoutingParams& params) override + const std::vector<std::string>& params) override { erasedHandler(req, asyncResp, params); } @@ -547,20 +496,11 @@ class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> template <typename Func, unsigned... Indices> std::function<void(const Request&, const std::shared_ptr<bmcweb::AsyncResp>&, - const RoutingParams&)> + const std::vector<std::string>&)> wrap(Func f, std::integer_sequence<unsigned, Indices...> /*is*/) { using function_t = crow::utility::FunctionTraits<Func>; - if (!black_magic::isParameterTagCompatible( - black_magic::getParameterTag(rule.c_str()), - black_magic::computeParameterTagFromArgsList< - typename function_t::template arg<Indices>...>::value)) - { - throw std::runtime_error("routeDynamic: Handler type is mismatched " - "with URL parameters: " + - rule); - } auto ret = detail::routing_handler_call_helper::Wrapped< Func, typename function_t::template arg<Indices>...>(); ret.template set<typename function_t::template arg<Indices>...>( @@ -578,7 +518,7 @@ class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> private: std::function<void(const Request&, const std::shared_ptr<bmcweb::AsyncResp>&, - const RoutingParams&)> + const std::vector<std::string>&)> erasedHandler; }; @@ -603,70 +543,13 @@ class TaggedRule : } template <typename Func> - typename std::enable_if< - black_magic::CallHelper<Func, black_magic::S<Args...>>::value, - void>::type - operator()(Func&& f) + void operator()(Func&& f) { static_assert( - black_magic::CallHelper<Func, black_magic::S<Args...>>::value || - black_magic::CallHelper< - Func, black_magic::S<crow::Request, Args...>>::value, - "Handler type is mismatched with URL parameters"); - static_assert( - !std::is_same<void, decltype(f(std::declval<Args>()...))>::value, - "Handler function cannot have void return type; valid return " - "types: " - "string, int, crow::response, nlohmann::json"); - - handler = [f = std::forward<Func>(f)]( - const Request&, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - Args... args) { asyncResp->res.result(f(args...)); }; - } - - template <typename Func> - typename std::enable_if< - !black_magic::CallHelper<Func, black_magic::S<Args...>>::value && black_magic::CallHelper< - Func, black_magic::S<crow::Request, Args...>>::value, - void>::type - operator()(Func&& f) - { - static_assert( - black_magic::CallHelper<Func, black_magic::S<Args...>>::value || - black_magic::CallHelper< - Func, black_magic::S<crow::Request, Args...>>::value, - "Handler type is mismatched with URL parameters"); - static_assert( - !std::is_same<void, decltype(f(std::declval<crow::Request>(), - std::declval<Args>()...))>::value, - "Handler function cannot have void return type; valid return " - "types: " - "string, int, crow::response,nlohmann::json"); - - handler = [f = std::forward<Func>(f)]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - Args... args) { asyncResp->res.result(f(req, args...)); }; - } - - template <typename Func> - typename std::enable_if< - !black_magic::CallHelper<Func, black_magic::S<Args...>>::value && - !black_magic::CallHelper< - Func, black_magic::S<crow::Request, Args...>>::value, - void>::type - operator()(Func&& f) - { - static_assert( - black_magic::CallHelper<Func, black_magic::S<Args...>>::value || - black_magic::CallHelper< - Func, black_magic::S<crow::Request, Args...>>::value || - black_magic::CallHelper< - Func, black_magic::S<crow::Request, - std::shared_ptr<bmcweb::AsyncResp>&, - Args...>>::value, + Func, black_magic::S<crow::Request, + std::shared_ptr<bmcweb::AsyncResp>&, + Args...>>::value, "Handler type is mismatched with URL parameters"); static_assert( std::is_same< @@ -674,9 +557,7 @@ class TaggedRule : decltype(f(std::declval<crow::Request>(), std::declval<std::shared_ptr<bmcweb::AsyncResp>&>(), std::declval<Args>()...))>::value, - "Handler function with response argument should have void " - "return " - "type"); + "Handler function with response argument should have void return type"); handler = std::forward<Func>(f); } @@ -690,11 +571,11 @@ class TaggedRule : void handle(const Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const RoutingParams& params) override + const std::vector<std::string>& params) override { detail::routing_handler_call_helper::Call< detail::routing_handler_call_helper::CallParams<decltype(handler)>, - 0, 0, 0, 0, black_magic::S<Args...>, black_magic::S<>>()( + 0, black_magic::S<Args...>, black_magic::S<>>()( detail::routing_handler_call_helper::CallParams<decltype(handler)>{ handler, params, req, asyncResp}); } @@ -825,18 +706,18 @@ class Trie } } - std::pair<unsigned, RoutingParams> - find(std::string_view reqUrl, const Node* node = nullptr, - size_t pos = 0, RoutingParams* params = nullptr) const + std::pair<unsigned, std::vector<std::string>> + find(const std::string_view reqUrl, const Node* node = nullptr, + size_t pos = 0, std::vector<std::string>* params = nullptr) const { - RoutingParams empty; + std::vector<std::string> empty; if (params == nullptr) { params = ∅ } unsigned found{}; - RoutingParams matchParams; + std::vector<std::string> matchParams; if (node == nullptr) { @@ -848,7 +729,8 @@ class Trie } auto updateFound = - [&found, &matchParams](std::pair<unsigned, RoutingParams>& ret) { + [&found, + &matchParams](std::pair<unsigned, std::vector<std::string>>& ret) { if (ret.first != 0U && (found == 0U || found > ret.first)) { found = ret.first; @@ -856,74 +738,6 @@ class Trie } }; - if (node->paramChildrens[static_cast<size_t>(ParamType::INT)] != 0U) - { - char c = reqUrl[pos]; - if ((c >= '0' && c <= '9') || c == '+' || c == '-') - { - char* eptr = nullptr; - errno = 0; - long long int value = - std::strtoll(reqUrl.data() + pos, &eptr, 10); - if (errno != ERANGE && eptr != reqUrl.data() + pos) - { - params->intParams.push_back(value); - std::pair<unsigned, RoutingParams> ret = - find(reqUrl, - &nodes[node->paramChildrens[static_cast<size_t>( - ParamType::INT)]], - static_cast<size_t>(eptr - reqUrl.data()), params); - updateFound(ret); - params->intParams.pop_back(); - } - } - } - - if (node->paramChildrens[static_cast<size_t>(ParamType::UINT)] != 0U) - { - char c = reqUrl[pos]; - if ((c >= '0' && c <= '9') || c == '+') - { - char* eptr = nullptr; - errno = 0; - unsigned long long int value = - std::strtoull(reqUrl.data() + pos, &eptr, 10); - if (errno != ERANGE && eptr != reqUrl.data() + pos) - { - params->uintParams.push_back(value); - std::pair<unsigned, RoutingParams> ret = - find(reqUrl, - &nodes[node->paramChildrens[static_cast<size_t>( - ParamType::UINT)]], - static_cast<size_t>(eptr - reqUrl.data()), params); - updateFound(ret); - params->uintParams.pop_back(); - } - } - } - - if (node->paramChildrens[static_cast<size_t>(ParamType::DOUBLE)] != 0U) - { - char c = reqUrl[pos]; - if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.') - { - char* eptr = nullptr; - errno = 0; - double value = std::strtod(reqUrl.data() + pos, &eptr); - if (errno != ERANGE && eptr != reqUrl.data() + pos) - { - params->doubleParams.push_back(value); - std::pair<unsigned, RoutingParams> ret = - find(reqUrl, - &nodes[node->paramChildrens[static_cast<size_t>( - ParamType::DOUBLE)]], - static_cast<size_t>(eptr - reqUrl.data()), params); - updateFound(ret); - params->doubleParams.pop_back(); - } - } - } - if (node->paramChildrens[static_cast<size_t>(ParamType::STRING)] != 0U) { size_t epos = pos; @@ -937,15 +751,14 @@ class Trie if (epos != pos) { - params->stringParams.emplace_back( - reqUrl.substr(pos, epos - pos)); - std::pair<unsigned, RoutingParams> ret = + params->emplace_back(reqUrl.substr(pos, epos - pos)); + std::pair<unsigned, std::vector<std::string>> ret = find(reqUrl, &nodes[node->paramChildrens[static_cast<size_t>( ParamType::STRING)]], epos, params); updateFound(ret); - params->stringParams.pop_back(); + params->pop_back(); } } @@ -955,15 +768,14 @@ class Trie if (epos != pos) { - params->stringParams.emplace_back( - reqUrl.substr(pos, epos - pos)); - std::pair<unsigned, RoutingParams> ret = + params->emplace_back(reqUrl.substr(pos, epos - pos)); + std::pair<unsigned, std::vector<std::string>> ret = find(reqUrl, &nodes[node->paramChildrens[static_cast<size_t>( ParamType::PATH)]], epos, params); updateFound(ret); - params->stringParams.pop_back(); + params->pop_back(); } } @@ -974,7 +786,7 @@ class Trie if (reqUrl.compare(pos, fragment.size(), fragment) == 0) { - std::pair<unsigned, RoutingParams> ret = + std::pair<unsigned, std::vector<std::string>> ret = find(reqUrl, child, pos + fragment.size(), params); updateFound(ret); } @@ -992,18 +804,16 @@ class Trie char c = url[i]; if (c == '<') { - const static std::array<std::pair<ParamType, std::string>, 7> + constexpr static std::array< + std::pair<ParamType, std::string_view>, 3> paramTraits = {{ - {ParamType::INT, "<int>"}, - {ParamType::UINT, "<uint>"}, - {ParamType::DOUBLE, "<float>"}, - {ParamType::DOUBLE, "<double>"}, {ParamType::STRING, "<str>"}, {ParamType::STRING, "<string>"}, {ParamType::PATH, "<path>"}, }}; - for (const std::pair<ParamType, std::string>& x : paramTraits) + for (const std::pair<ParamType, std::string_view>& x : + paramTraits) { if (url.compare(i, x.second.size(), x.second) == 0) { @@ -1050,15 +860,6 @@ class Trie 2U * level, ' ') /*<< "("<<n->paramChildrens[i]<<") "*/; switch (static_cast<ParamType>(i)) { - case ParamType::INT: - BMCWEB_LOG_DEBUG << "<int>"; - break; - case ParamType::UINT: - BMCWEB_LOG_DEBUG << "<uint>"; - break; - case ParamType::DOUBLE: - BMCWEB_LOG_DEBUG << "<float>"; - break; case ParamType::STRING: BMCWEB_LOG_DEBUG << "<str>"; break; @@ -1188,7 +989,7 @@ class Router struct FindRoute { BaseRule* rule = nullptr; - RoutingParams params; + std::vector<std::string> params; }; struct FindRouteResponse @@ -1206,7 +1007,8 @@ class Router return route; } const PerMethod& perMethod = perMethods[index]; - std::pair<unsigned, RoutingParams> found = perMethod.trie.find(url); + std::pair<unsigned, std::vector<std::string>> found = + perMethod.trie.find(url); if (found.first >= perMethod.rules.size()) { throw std::runtime_error("Trie internal structure corrupted!"); @@ -1409,7 +1211,7 @@ class Router Trie& trie = perMethod.trie; std::vector<BaseRule*>& rules = perMethod.rules; - const std::pair<unsigned, RoutingParams>& found = + const std::pair<unsigned, std::vector<std::string>>& found = trie.find(req.url().encoded_path()); unsigned ruleIndex = found.first; if (ruleIndex == 0U) @@ -1504,7 +1306,7 @@ class Router } BaseRule& rule = *foundRoute.route.rule; - RoutingParams params = std::move(foundRoute.route.params); + std::vector<std::string> params = std::move(foundRoute.route.params); BMCWEB_LOG_DEBUG << "Matched rule '" << rule.rule << "' " << static_cast<uint32_t>(*verb) << " / " |