diff options
| author | Matt Spinler <spinler@us.ibm.com> | 2019-01-15 11:53:13 -0600 |
|---|---|---|
| committer | Matt Spinler <spinler@us.ibm.com> | 2019-01-21 14:01:04 -0600 |
| commit | 39a4e39f7d85c3a54975e2cf36a636f8feefe7ae (patch) | |
| tree | 3644111f55e3908d84fb29266c4ec71cb79474d1 /include | |
| parent | 89c1970b718ae26497d3f7c9ac5e596fa2fb3968 (diff) | |
| download | bmcweb-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.hpp | 59 |
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, |

