1 #pragma once 2 3 #include "bmcweb_config.h" 4 5 #include "app.hpp" 6 #include "async_resp.hpp" 7 #include "error_messages.hpp" 8 #include "http_request.hpp" 9 #include "http_response.hpp" 10 #include "logging.hpp" 11 #include "utils/query_param.hpp" 12 13 #include <boost/beast/http/verb.hpp> 14 #include <boost/url/params_view.hpp> 15 #include <boost/url/url_view.hpp> 16 17 #include <functional> 18 #include <memory> 19 #include <new> 20 #include <optional> 21 #include <string> 22 #include <string_view> 23 #include <type_traits> 24 #include <utility> 25 26 // IWYU pragma: no_forward_declare crow::App 27 // IWYU pragma: no_include <boost/url/impl/params_view.hpp> 28 // IWYU pragma: no_include <boost/url/impl/url_view.hpp> 29 30 namespace redfish 31 { 32 33 // Sets up the Redfish Route and delegates some of the query parameter 34 // processing. |queryCapabilities| stores which query parameters will be 35 // handled by redfish-core/lib codes, then default query parameter handler won't 36 // process these parameters. 37 [[nodiscard]] inline bool setUpRedfishRouteWithDelegation( 38 crow::App& app, const crow::Request& req, 39 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 40 query_param::Query& delegated, 41 const query_param::QueryCapabilities& queryCapabilities) 42 { 43 BMCWEB_LOG_DEBUG << "setup redfish route"; 44 45 // Section 7.4 of the redfish spec "Redfish Services shall process the 46 // [OData-Version header] in the following table as defined by the HTTP 1.1 47 // specification..." 48 // Required to pass redfish-protocol-validator REQ_HEADERS_ODATA_VERSION 49 std::string_view odataHeader = req.getHeaderValue("OData-Version"); 50 if (!odataHeader.empty() && odataHeader != "4.0") 51 { 52 messages::preconditionFailed(asyncResp->res); 53 return false; 54 } 55 56 asyncResp->res.addHeader("OData-Version", "4.0"); 57 58 std::optional<query_param::Query> queryOpt = 59 query_param::parseParameters(req.urlView.params(), asyncResp->res); 60 if (queryOpt == std::nullopt) 61 { 62 return false; 63 } 64 65 // If this isn't a get, no need to do anything with parameters 66 if (req.method() != boost::beast::http::verb::get) 67 { 68 return true; 69 } 70 71 delegated = query_param::delegate(queryCapabilities, *queryOpt); 72 std::function<void(crow::Response&)> handler = 73 asyncResp->res.releaseCompleteRequestHandler(); 74 asyncResp->res.setCompleteRequestHandler( 75 [&app, handler(std::move(handler)), 76 query{*queryOpt}](crow::Response& resIn) mutable { 77 processAllParams(app, query, handler, resIn); 78 }); 79 return true; 80 } 81 82 // Sets up the Redfish Route. All parameters are handled by the default handler. 83 [[nodiscard]] inline bool 84 setUpRedfishRoute(crow::App& app, const crow::Request& req, 85 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 86 { 87 // This route |delegated| is never used 88 query_param::Query delegated; 89 return setUpRedfishRouteWithDelegation(app, req, asyncResp, delegated, 90 query_param::QueryCapabilities{}); 91 } 92 } // namespace redfish 93