summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2019-01-15 11:53:13 -0600
committerMatt Spinler <spinler@us.ibm.com>2019-01-21 14:01:04 -0600
commit39a4e39f7d85c3a54975e2cf36a636f8feefe7ae (patch)
tree3644111f55e3908d84fb29266c4ec71cb79474d1 /include
parent89c1970b718ae26497d3f7c9ac5e596fa2fb3968 (diff)
downloadbmcweb-39a4e39f7d85c3a54975e2cf36a636f8feefe7ae.tar.gz
bmcweb-39a4e39f7d85c3a54975e2cf36a636f8feefe7ae.zip
REST: If necessary, combine method response data
There is a possibility that a method may be implemented by either different services or interfaces, and 1 or more of them may return data. In the unlikely case that is encountered, attempt to handle that by first setting the final response data to the first data back from a method, and then on future method responses that return data: * If the new and old responses are both dictionaries, add the new keys/values to the original ones. * If the new and old responses are both arrays, add the new array elements to the original array. * If the new data is of a different type than the previous data, convert the overall response into an array and add the new and original responses as array elements. Change-Id: I23edc3d9f8154aba1ba4276112cde6ecb4345fdf Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Diffstat (limited to 'include')
-rw-r--r--include/openbmc_dbus_rest.hpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp
index 9f282a6..e310b1a 100644
--- a/include/openbmc_dbus_rest.hpp
+++ b/include/openbmc_dbus_rest.hpp
@@ -462,6 +462,7 @@ struct InProgressActionData
bool methodPassed = false;
bool methodFailed = false;
bool outputFailed = false;
+ bool convertedToArray = false;
nlohmann::json methodResponse;
nlohmann::json arguments;
};
@@ -1190,6 +1191,64 @@ void handleMethodResponse(std::shared_ptr<InProgressActionData> transaction,
sdbusplus::message::message &m,
const std::string &returnType)
{
+ nlohmann::json data;
+
+ int r = convertDBusToJSON(returnType, m, data);
+ if (r < 0)
+ {
+ transaction->outputFailed = true;
+ return;
+ }
+
+ if (data.is_null())
+ {
+ return;
+ }
+
+ if (transaction->methodResponse.is_null())
+ {
+ transaction->methodResponse = std::move(data);
+ return;
+ }
+
+ // If they're both dictionaries or arrays, merge into one.
+ // Otherwise, make the results an array with every result
+ // an entry. Could also just fail in that case, but it
+ // seems better to get the data back somehow.
+
+ if (transaction->methodResponse.is_object() && data.is_object())
+ {
+ for (const auto &obj : data.items())
+ {
+ // Note: Will overwrite the data for a duplicate key
+ transaction->methodResponse.emplace(obj.key(),
+ std::move(obj.value()));
+ }
+ return;
+ }
+
+ if (transaction->methodResponse.is_array() && data.is_array())
+ {
+ for (auto &obj : data)
+ {
+ transaction->methodResponse.push_back(std::move(obj));
+ }
+ return;
+ }
+
+ if (!transaction->convertedToArray)
+ {
+ // They are different types. May as well turn them into an array
+ nlohmann::json j = std::move(transaction->methodResponse);
+ transaction->methodResponse = nlohmann::json::array();
+ transaction->methodResponse.push_back(std::move(j));
+ transaction->methodResponse.push_back(std::move(data));
+ transaction->convertedToArray = true;
+ }
+ else
+ {
+ transaction->methodResponse.push_back(std::move(data));
+ }
}
void findActionOnInterface(std::shared_ptr<InProgressActionData> transaction,
OpenPOWER on IntegriCloud