| #ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_ |
| #define THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_ |
| |
| #include <array> |
| #include <cstddef> |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/base/thread_annotations.h" |
| #include "absl/container/flat_hash_map.h" |
| #include "absl/container/flat_hash_set.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/synchronization/mutex.h" |
| #include "boost/asio/io_context.hpp" // NOLINT |
| #include "boost/beast/http/message.hpp" //NOLINT |
| #include "boost/beast/http/string_body.hpp" //NOLINT |
| #include "boost/beast/http/verb.hpp" // NOLINT |
| #include "boost/system/error_code.hpp" // NOLINT |
| #include "boost/url/parse.hpp" // NOLINT |
| #include "boost/url/url.hpp" // NOLINT |
| #include "http_request.hpp" |
| #include "async_resp.hpp" |
| #include "utility.hpp" |
| #include "app_interface.h" |
| #include "router_interface.h" |
| #include "routing.hpp" |
| |
| // DO NOT MODIFY THIS FILE IN GERRIT. THIS FILE SHOULD ONLY BE MODIFIED IN G3 |
| |
| namespace crow { |
| |
| namespace internal { |
| |
| struct Node { |
| absl::flat_hash_map<std::string, Node> children; |
| bool is_leaf = false; |
| }; |
| |
| // The class is thread compatible. |
| class SimpleTrie { |
| public: |
| explicit SimpleTrie(const absl::flat_hash_set<std::string>& subtrees); |
| ~SimpleTrie() = default; |
| |
| // This SimpleTrie is not going to validate the URL is actually a valid URL. |
| // As the input of this function in our use case comes from a valid Redfish |
| // request, the url is guaranteed to be a valid URL. |
| bool IsUrlInSubtrees(std::string_view url) const; |
| |
| void DebugPrint() const; |
| |
| protected: |
| void AddSubtree(std::string_view subtree); |
| |
| private: |
| Node root_; |
| const absl::flat_hash_set<std::string> subtrees_; |
| }; |
| |
| } // namespace internal |
| |
| // This router will automatically route the requests to the appropriate |
| // router based on the request path. |
| class SmartRouter : public RouterInterface { |
| public: |
| // Clang thinks that the following constructor is deleted, but on gcc, it is |
| // not. |
| SmartRouter() : tlbmc_owned_subtrees_({}) {}; // NOLINT |
| ~SmartRouter() override = default; |
| |
| SmartRouter(const SmartRouter&) = delete; |
| SmartRouter& operator=(const SmartRouter&) = delete; |
| SmartRouter(SmartRouter&&) = delete; |
| SmartRouter& operator=(SmartRouter&&) = delete; |
| |
| SmartRouter(bool allow_session_empty, AppInterface* tlbmc_app); |
| |
| void Validate(); |
| |
| void Handle(crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& async_resp) override; |
| |
| // This is a wrapper around the gbmcweb router's handleUpgrade function. |
| template <typename Adaptor> |
| void HandleUpgrade(Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| Adaptor&& adaptor) { |
| gbmcweb_router_.handleUpgrade(req, asyncResp, |
| std::forward<Adaptor>(adaptor)); |
| } |
| |
| DynamicRule& NewRuleDynamic(std::string&& rule); |
| |
| std::vector<const std::string*> GetRoutes(const std::string& parent); |
| |
| void DebugPrint(); |
| |
| template <uint64_t N> |
| typename black_magic::Arguments< |
| N>::type::template rebind<TaggedRule>& |
| NewRuleTagged(std::string_view rule) { |
| return gbmcweb_router_.newRuleTagged<N>(rule); |
| } |
| |
| // Plugin Routes |
| template <uint64_t Tag, typename Func, size_t N> |
| void AddHandler(absl::string_view url, boost::beast::http::verb verb, |
| const std::array<redfish::Privileges, N>& p, Func&& func) { |
| gbmcweb_router_.newRuleTagged<Tag>(url).methods(verb).privileges(p)(func); |
| // TODO(b/396518102): Add support for plugins in tlbmc. |
| // tlbmc_app_->AddRoute<Tag>(url).methods(verb)(func); |
| } |
| |
| template <uint64_t Tag, typename Func> |
| void ReplaceHandler(std::string_view url, boost::beast::http::verb verb, |
| Func&& func) { |
| gbmcweb_router_.replaceHandler<Tag>(url, verb, func); |
| // TODO(b/396518102): Add support for plugins in tlbmc. |
| // tlbmc_app_->ReplaceHandler<Tag>(url, verb, func); |
| } |
| |
| template <uint64_t Tag> |
| void RemoveHandler(std::string_view url, boost::beast::http::verb verb) { |
| gbmcweb_router_.removeRuleTagged<Tag>(url, verb); |
| // TODO(b/396518102): Add support for plugins in tlbmc. |
| // tlbmc_app_->RemoveHandler<Tag>(url, verb); |
| } |
| template <uint64_t Tag, typename Func> |
| void AppendHandler(std::string_view url, boost::beast::http::verb verb, |
| Func&& func) { |
| gbmcweb_router_.appendHandler<Tag>(url, verb, func); |
| // TODO(b/396518102): Add support for plugins in tlbmc. |
| // tlbmc_app_->AppendHandler<Tag>(url, verb, func); |
| } |
| |
| bool IsTlbmcOwnedUrl(std::string_view url, boost::beast::http::verb verb); |
| |
| Router& GetGbmcwebRouter() { return gbmcweb_router_; } |
| |
| void UpdateTlbmcOwnedUrls() override; |
| |
| protected: |
| // Store both the gbmcweb and tlbmc routers. |
| Router gbmcweb_router_ = Router(true); |
| AppInterface* const tlbmc_app_ = nullptr; |
| absl::Mutex tlbmc_owned_urls_mutex_; |
| absl::flat_hash_map<std::string, size_t> tlbmc_owned_urls_ |
| ABSL_GUARDED_BY(tlbmc_owned_urls_mutex_); |
| |
| private: |
| absl::flat_hash_map<std::string, size_t> GetTlbmcOwnedUrls(); |
| absl::flat_hash_set<std::string> GetTlbmcOwnedSubtrees(); |
| const internal::SimpleTrie tlbmc_owned_subtrees_; |
| }; |
| |
| } // namespace crow |
| |
| #endif // THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_ |