| #ifndef THIRD_PARTY_GBMCWEB_HTTP_APP_H_ | |
| #define THIRD_PARTY_GBMCWEB_HTTP_APP_H_ | |
| #include "boost/asio/io_context.hpp" // NOLINT | |
| #include "boost/asio/ip/tcp.hpp" // NOLINT | |
| #include "redfish_devpath_injector_interface.hpp" | |
| #include "http_request.hpp" | |
| #include "routing.hpp" | |
| #include "async_resp.hpp" | |
| #include "privileges.hpp" | |
| #include "app_interface.h" | |
| #include "smart_router.h" | |
| #ifdef BMCWEB_ENABLE_SSL | |
| #include "boost/asio/ssl/context.hpp" // NOLINT | |
| #include "boost/beast/ssl/ssl_stream.hpp" // NOLINT | |
| #endif | |
| #include <array> | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <memory> | |
| #include <string> | |
| #include <string_view> | |
| #include <type_traits> | |
| #include <utility> | |
| #include <vector> | |
| // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) | |
| #define BMCWEB_ROUTE(app, url) \ | |
| app.template route<crow::black_magic::getParameterTag(url)>(url) | |
| #ifdef BMCWEB_ENABLE_SSL | |
| using ssl_context_t = boost::asio::ssl::context; | |
| using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>; | |
| #else | |
| using socket_t = boost::asio::ip::tcp::socket; | |
| #endif | |
| namespace crow { | |
| class App { | |
| public: | |
| explicit App(bool allowSessionEmpty, | |
| std::shared_ptr<boost::asio::io_context> ioIn = | |
| std::make_shared<boost::asio::io_context>(), | |
| AppInterface* tlbmc_app = nullptr, | |
| devpath_plugin::RedfishDevpathInjectorInterface* | |
| devpath_injector = nullptr) | |
| : io(std::move(ioIn)), | |
| router(std::make_unique<SmartRouter>(allowSessionEmpty, tlbmc_app)), | |
| devpathInjector(devpath_injector) {} | |
| App(std::shared_ptr<boost::asio::io_context> ioIn, | |
| std::unique_ptr<SmartRouter> router) | |
| : io(std::move(ioIn)), router(std::move(router)) {} | |
| App() = default; | |
| virtual ~App() { this->stop(); } | |
| App(const App&) = delete; | |
| App(App&&) = delete; | |
| App& operator=(const App&) = delete; | |
| App& operator=(const App&&) = delete; | |
| template <typename Adaptor> | |
| void handleUpgrade(Request& req, | |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | |
| Adaptor&& adaptor) { | |
| router->HandleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor)); | |
| } | |
| virtual void handle(Request& req, | |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp); | |
| DynamicRule& routeDynamic(std::string&& rule) { | |
| return router->NewRuleDynamic(std::move(rule)); | |
| } | |
| template <uint64_t Tag> | |
| auto& route(std::string&& rule) { | |
| return router->NewRuleTagged<Tag>(std::move(rule)); | |
| } | |
| App& socket(int existingSocket) { | |
| socketFd = existingSocket; | |
| return *this; | |
| } | |
| App& port(std::uint16_t port) { | |
| portUint = port; | |
| return *this; | |
| } | |
| App& bindaddr(std::string bindaddr) { | |
| bindaddrStr = std::move(bindaddr); | |
| return *this; | |
| } | |
| void validate() { router->Validate(); } | |
| void run(); | |
| void stop() { | |
| if (io != nullptr) { | |
| io->stop(); | |
| } | |
| } | |
| void debugPrint(); | |
| std::vector<const std::string*> getRoutes() { | |
| const std::string root; | |
| return router->GetRoutes(root); | |
| } | |
| std::vector<const std::string*> getRoutes(const std::string& parent) { | |
| return router->GetRoutes(parent); | |
| } | |
| template <uint64_t Tag, typename Func, size_t N> | |
| void addHandler(std::string_view url, boost::beast::http::verb verb, | |
| const std::array<redfish::Privileges, N>& p, Func&& func) { | |
| router->NewRuleTagged<Tag>(url).methods(verb).privileges(p)(func); | |
| } | |
| template <uint64_t Tag, typename Func> | |
| void replaceHandler(std::string_view url, boost::beast::http::verb verb, | |
| Func&& func) { | |
| router->ReplaceHandler<Tag>(url, verb, func); | |
| } | |
| template <uint64_t Tag> | |
| void removeHandler(std::string_view url, boost::beast::http::verb verb) { | |
| router->RemoveHandler<Tag>(url, verb); | |
| } | |
| template <uint64_t Tag, typename Func> | |
| void appendHandler(std::string_view url, boost::beast::http::verb verb, | |
| Func&& func) { | |
| router->AppendHandler<Tag>(url, verb, func); | |
| } | |
| #ifdef BMCWEB_ENABLE_SSL | |
| App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx) { | |
| sslContext = std::move(ctx); | |
| BMCWEB_LOG_INFO << "app::ssl context use_count=" << sslContext.use_count(); | |
| return *this; | |
| } | |
| std::shared_ptr<ssl_context_t> sslContext = nullptr; | |
| #else | |
| template <typename T> | |
| App& ssl(T&& /*unused*/) { | |
| // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is | |
| // defined. | |
| static_assert( | |
| // make static_assert dependent to T; always false | |
| std::is_base_of<T, void>::value, | |
| "Define BMCWEB_ENABLE_SSL to enable ssl support."); | |
| return *this; | |
| } | |
| #endif | |
| devpath_plugin::RedfishDevpathInjectorInterface* GetDevpathInjector() const { | |
| return devpathInjector; | |
| } | |
| private: | |
| std::shared_ptr<boost::asio::io_context> io; | |
| #ifdef BMCWEB_ENABLE_SSL | |
| uint16_t portUint = 443; | |
| #else | |
| uint16_t portUint = 80; // NOLINT | |
| #endif | |
| std::string bindaddrStr = "0.0.0.0"; // NOLINT | |
| int socketFd = -1; // NOLINT | |
| std::unique_ptr<SmartRouter> router; // NOLINT | |
| devpath_plugin::RedfishDevpathInjectorInterface* devpathInjector = nullptr; | |
| }; | |
| } // namespace crow | |
| using App = crow::App; | |
| #endif // THIRD_PARTY_GBMCWEB_HTTP_APP_H_ |