summaryrefslogtreecommitdiff
path: root/redfish-core
diff options
context:
space:
mode:
authorNan Zhou <nanzhoumails@gmail.com>2022-04-04 23:10:40 +0300
committerNan Zhou <nanzhoumails@gmail.com>2022-04-11 18:42:01 +0300
commita6b9125ff91500afed34dc923e9bafb90da75ec4 (patch)
treecd2861d1acf386de01aeaa19866adfb8759eced0 /redfish-core
parentbacb216228c45ca715163f4c81717b1af39889ab (diff)
downloadbmcweb-a6b9125ff91500afed34dc923e9bafb90da75ec4.tar.xz
query parameter: add a way to delegate certain parameter
The generic query parameter handlers might not be performant, e.g., Expand in the sensor collections. This change adds a way to delegate query parameter processsing to redfish-core codes: 1. introduced a separate struct in the setUpRedfishRoute function, with which redfish-core codes can easily set delegation for each parameter; for example, the children patch of this PR will implement an efficient handler for sensor collection Expand, top, and skip. 2. introduced a separate Redfish route for delegation; this routes takes the struct described above and changes the query object so that query parameters are delegated. 3. in order to avoid copying Query objects and run delegation check twice, the |setUpRedfishRouteWithDelegation| function sets |delegated| so that callers can directly use it to determinte if delegation is needed, and what delegated Queries are Tested: 1. added unit tests 2. the default redfish route is still working correctly Signed-off-by: Nan Zhou <nanzhoumails@gmail.com> Change-Id: I77597ad7e8b40ac179d86dc9be1a35767cc61284
Diffstat (limited to 'redfish-core')
-rw-r--r--redfish-core/include/query.hpp24
-rw-r--r--redfish-core/include/utils/query_param.hpp47
-rw-r--r--redfish-core/include/utils/query_param_test.cpp61
3 files changed, 127 insertions, 5 deletions
diff --git a/redfish-core/include/query.hpp b/redfish-core/include/query.hpp
index 7db370d9fb..4dd03c622c 100644
--- a/redfish-core/include/query.hpp
+++ b/redfish-core/include/query.hpp
@@ -7,9 +7,14 @@
namespace redfish
{
-[[nodiscard]] inline bool setUpRedfishRoute(crow::App& app,
- const crow::Request& req,
- crow::Response& res)
+// Sets up the Redfish Route and delegates some of the query parameter
+// processing. |queryCapabilities| stores which query parameters will be
+// handled by redfish-core/lib codes, then default query parameter handler won't
+// process these parameters.
+[[nodiscard]] inline bool setUpRedfishRouteWithDelegation(
+ crow::App& app, const crow::Request& req, crow::Response& res,
+ query_param::Query& delegated,
+ const query_param::QueryCapabilities& queryCapabilities)
{
BMCWEB_LOG_DEBUG << "setup redfish route";
@@ -42,9 +47,9 @@ namespace redfish
return true;
}
+ delegated = query_param::delegate(queryCapabilities, *queryOpt);
std::function<void(crow::Response&)> handler =
res.releaseCompleteRequestHandler();
-
res.setCompleteRequestHandler(
[&app, handler(std::move(handler)),
query{*queryOpt}](crow::Response& res) mutable {
@@ -52,4 +57,15 @@ namespace redfish
});
return true;
}
+
+// Sets up the Redfish Route. All parameters are handled by the default handler.
+[[nodiscard]] inline bool setUpRedfishRoute(crow::App& app,
+ const crow::Request& req,
+ crow::Response& res)
+{
+ // This route |delegated| is never used
+ query_param::Query delegated;
+ return setUpRedfishRouteWithDelegation(app, req, res, delegated,
+ query_param::QueryCapabilities{});
+}
} // namespace redfish
diff --git a/redfish-core/include/utils/query_param.hpp b/redfish-core/include/utils/query_param.hpp
index 7aef2f0923..60e572fccc 100644
--- a/redfish-core/include/utils/query_param.hpp
+++ b/redfish-core/include/utils/query_param.hpp
@@ -24,13 +24,58 @@ enum class ExpandType : uint8_t
Both,
};
+// The struct stores the parsed query parameters of the default Redfish route.
struct Query
{
+ // Only
bool isOnly = false;
- uint8_t expandLevel = 1;
+ // Expand
+ uint8_t expandLevel = 0;
ExpandType expandType = ExpandType::None;
};
+// The struct defines how resource handlers in redfish-core/lib/ can handle
+// query parameters themselves, so that the default Redfish route will delegate
+// the processing.
+struct QueryCapabilities
+{
+ bool canDelegateOnly = false;
+ uint8_t canDelegateExpandLevel = 0;
+};
+
+// Delegates query parameters according to the given |queryCapabilities|
+// This function doesn't check query parameter conflicts since the parse
+// function will take care of it.
+// Returns a delegated query object which can be used by individual resource
+// handlers so that handlers don't need to query again.
+inline Query delegate(const QueryCapabilities& queryCapabilities, Query& query)
+{
+ Query delegated;
+ // delegate only
+ if (query.isOnly && queryCapabilities.canDelegateOnly)
+ {
+ delegated.isOnly = true;
+ query.isOnly = false;
+ }
+ // delegate expand as much as we can
+ if (query.expandType != ExpandType::None)
+ {
+ delegated.expandType = query.expandType;
+ if (query.expandLevel <= queryCapabilities.canDelegateExpandLevel)
+ {
+ query.expandType = ExpandType::None;
+ delegated.expandLevel = query.expandLevel;
+ query.expandLevel = 0;
+ }
+ else
+ {
+ query.expandLevel -= queryCapabilities.canDelegateExpandLevel;
+ delegated.expandLevel = queryCapabilities.canDelegateExpandLevel;
+ }
+ }
+ return delegated;
+}
+
inline bool getExpandType(std::string_view value, Query& query)
{
if (value.empty())
diff --git a/redfish-core/include/utils/query_param_test.cpp b/redfish-core/include/utils/query_param_test.cpp
index 69ed673f6d..7a2da712c2 100644
--- a/redfish-core/include/utils/query_param_test.cpp
+++ b/redfish-core/include/utils/query_param_test.cpp
@@ -7,6 +7,67 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+namespace redfish::query_param
+{
+namespace
+{
+
+TEST(Delegate, OnlyPositive)
+{
+ Query query{
+ .isOnly = true,
+ };
+ QueryCapabilities capabilities{
+ .canDelegateOnly = true,
+ };
+ Query delegated = delegate(capabilities, query);
+ EXPECT_TRUE(delegated.isOnly);
+ EXPECT_FALSE(query.isOnly);
+}
+
+TEST(Delegate, ExpandPositive)
+{
+ Query query{
+ .isOnly = false,
+ .expandLevel = 5,
+ .expandType = ExpandType::Both,
+ };
+ QueryCapabilities capabilities{
+ .canDelegateExpandLevel = 3,
+ };
+ Query delegated = delegate(capabilities, query);
+ EXPECT_FALSE(delegated.isOnly);
+ EXPECT_EQ(delegated.expandLevel, capabilities.canDelegateExpandLevel);
+ EXPECT_EQ(delegated.expandType, ExpandType::Both);
+ EXPECT_EQ(query.expandLevel, 2);
+}
+
+TEST(Delegate, OnlyNegative)
+{
+ Query query{
+ .isOnly = true,
+ };
+ QueryCapabilities capabilities{
+ .canDelegateOnly = false,
+ };
+ Query delegated = delegate(capabilities, query);
+ EXPECT_FALSE(delegated.isOnly);
+ EXPECT_EQ(query.isOnly, true);
+}
+
+TEST(Delegate, ExpandNegative)
+{
+ Query query{
+ .isOnly = false,
+ .expandType = ExpandType::None,
+ };
+ Query delegated = delegate(QueryCapabilities{}, query);
+ EXPECT_EQ(delegated.expandType, ExpandType::None);
+}
+
+} // namespace
+} // namespace redfish::query_param
+
TEST(QueryParams, ParseParametersOnly)
{
auto ret = boost::urls::parse_relative_ref("/redfish/v1?only");