xref: /openbmc/bmcweb/features/redfish/include/utils/query_param.hpp (revision f4c99e70dad320abf84fd25a32ad5fce2bf16f4a)
1 #pragma once
2 #include "app.hpp"
3 #include "async_resp.hpp"
4 #include "error_messages.hpp"
5 #include "http_request.hpp"
6 #include "routing.hpp"
7 
8 #include <string>
9 #include <string_view>
10 #include <vector>
11 
12 namespace redfish
13 {
14 namespace query_param
15 {
16 
17 struct Query
18 {
19     bool isOnly = false;
20 };
21 
22 inline std::optional<Query>
23     parseParameters(const boost::urls::params_view& urlParams,
24                     crow::Response& res)
25 {
26     Query ret;
27     for (const boost::urls::params_view::value_type& it : urlParams)
28     {
29         std::string_view key(it.key.data(), it.key.size());
30         std::string_view value(it.value.data(), it.value.size());
31         if (key == "only")
32         {
33             if (!it.value.empty())
34             {
35                 messages::queryParameterValueFormatError(res, value, key);
36                 return std::nullopt;
37             }
38             ret.isOnly = true;
39         }
40     }
41     return ret;
42 }
43 
44 inline bool processOnly(crow::App& app, crow::Response& res,
45                         std::function<void(crow::Response&)>& completionHandler)
46 {
47     BMCWEB_LOG_DEBUG << "Processing only query param";
48     auto itMembers = res.jsonValue.find("Members");
49     if (itMembers == res.jsonValue.end())
50     {
51         messages::queryNotSupportedOnResource(res);
52         completionHandler(res);
53         return false;
54     }
55     auto itMemBegin = itMembers->begin();
56     if (itMemBegin == itMembers->end() || itMembers->size() != 1)
57     {
58         BMCWEB_LOG_DEBUG << "Members contains " << itMembers->size()
59                          << " element, returning full collection.";
60         completionHandler(res);
61         return false;
62     }
63 
64     auto itUrl = itMemBegin->find("@odata.id");
65     if (itUrl == itMemBegin->end())
66     {
67         BMCWEB_LOG_DEBUG << "No found odata.id";
68         messages::internalError(res);
69         completionHandler(res);
70         return false;
71     }
72     const std::string* url = itUrl->get_ptr<const std::string*>();
73     if (url == nullptr)
74     {
75         BMCWEB_LOG_DEBUG << "@odata.id wasn't a string????";
76         messages::internalError(res);
77         completionHandler(res);
78         return false;
79     }
80     // TODO(Ed) copy request headers?
81     // newReq.session = req.session;
82     std::error_code ec;
83     crow::Request newReq({boost::beast::http::verb::get, *url, 11}, ec);
84     if (ec)
85     {
86         messages::internalError(res);
87         completionHandler(res);
88         return false;
89     }
90 
91     auto asyncResp = std::make_shared<bmcweb::AsyncResp>();
92     BMCWEB_LOG_DEBUG << "setting completion handler on " << &asyncResp->res;
93     asyncResp->res.setCompleteRequestHandler(std::move(completionHandler));
94     asyncResp->res.setIsAliveHelper(res.releaseIsAliveHelper());
95     app.handle(newReq, asyncResp);
96     return true;
97 }
98 
99 void processAllParams(crow::App& app, Query query,
100                       crow::Response& intermediateResponse,
101                       std::function<void(crow::Response&)>& completionHandler)
102 {
103     if (!completionHandler)
104     {
105         BMCWEB_LOG_DEBUG << "Function was invalid?";
106         return;
107     }
108 
109     BMCWEB_LOG_DEBUG << "Processing query params";
110     // If the request failed, there's no reason to even try to run query
111     // params.
112     if (intermediateResponse.resultInt() < 200 ||
113         intermediateResponse.resultInt() >= 400)
114     {
115         completionHandler(intermediateResponse);
116         return;
117     }
118     if (query.isOnly)
119     {
120         processOnly(app, intermediateResponse, completionHandler);
121         return;
122     }
123     completionHandler(intermediateResponse);
124 }
125 
126 } // namespace query_param
127 } // namespace redfish
128