| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1 | #pragma once | 
|  | 2 |  | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 3 | #include "common.hpp" | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 4 | #include "dbus_utility.hpp" | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 5 | #include "error_messages.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 6 | #include "http_request.hpp" | 
|  | 7 | #include "http_response.hpp" | 
|  | 8 | #include "logging.hpp" | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 9 | #include "privileges.hpp" | 
| Ratan Gupta | 6f35956 | 2019-04-03 10:39:08 +0530 | [diff] [blame] | 10 | #include "sessions.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 11 | #include "utility.hpp" | 
|  | 12 | #include "websocket.hpp" | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 13 |  | 
| Iwona Klimaszewska | c0a1c8a | 2019-07-12 18:26:38 +0200 | [diff] [blame] | 14 | #include <async_resp.hpp> | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 15 | #include <boost/container/flat_map.hpp> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 16 |  | 
| Ed Tanous | e0d918b | 2018-03-27 17:41:04 -0700 | [diff] [blame] | 17 | #include <cerrno> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 18 | #include <cstdint> | 
| Ed Tanous | e0d918b | 2018-03-27 17:41:04 -0700 | [diff] [blame] | 19 | #include <cstdlib> | 
| Ed Tanous | 3dac749 | 2017-08-02 13:46:20 -0700 | [diff] [blame] | 20 | #include <limits> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 21 | #include <memory> | 
|  | 22 | #include <tuple> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 23 | #include <utility> | 
|  | 24 | #include <vector> | 
| Ed Tanous | 9140a67 | 2017-04-24 17:01:32 -0700 | [diff] [blame] | 25 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 26 | namespace crow | 
|  | 27 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 28 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 29 | class BaseRule | 
|  | 30 | { | 
|  | 31 | public: | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 32 | BaseRule(const std::string& thisRule) : rule(thisRule) | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 33 | {} | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 34 |  | 
| Ed Tanous | 0c0084a | 2019-10-24 15:57:51 -0700 | [diff] [blame] | 35 | virtual ~BaseRule() = default; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 36 |  | 
| Ed Tanous | ecd6a3a | 2022-01-07 09:18:40 -0800 | [diff] [blame] | 37 | BaseRule(const BaseRule&) = delete; | 
|  | 38 | BaseRule(BaseRule&&) = delete; | 
|  | 39 | BaseRule& operator=(const BaseRule&) = delete; | 
|  | 40 | BaseRule& operator=(const BaseRule&&) = delete; | 
|  | 41 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 42 | virtual void validate() = 0; | 
|  | 43 | std::unique_ptr<BaseRule> upgrade() | 
|  | 44 | { | 
|  | 45 | if (ruleToUpgrade) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 46 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 47 | return std::move(ruleToUpgrade); | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 48 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 49 | return {}; | 
|  | 50 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 51 |  | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 52 | virtual void handle(const Request& /*req*/, | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 53 | const std::shared_ptr<bmcweb::AsyncResp>&, | 
|  | 54 | const RoutingParams&) = 0; | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 55 | virtual void handleUpgrade(const Request& /*req*/, Response& res, | 
|  | 56 | boost::asio::ip::tcp::socket&& /*adaptor*/) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 57 | { | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 58 | res.result(boost::beast::http::status::not_found); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 59 | res.end(); | 
|  | 60 | } | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 61 | #ifdef BMCWEB_ENABLE_SSL | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 62 | virtual void handleUpgrade( | 
|  | 63 | const Request& /*req*/, Response& res, | 
|  | 64 | boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&& /*adaptor*/) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 65 | { | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 66 | res.result(boost::beast::http::status::not_found); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 67 | res.end(); | 
|  | 68 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 69 | #endif | 
|  | 70 |  | 
| Ed Tanous | 9eb808c | 2022-01-25 10:19:23 -0800 | [diff] [blame] | 71 | size_t getMethods() const | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 72 | { | 
|  | 73 | return methodsBitfield; | 
|  | 74 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 75 |  | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 76 | bool checkPrivileges(const redfish::Privileges& userPrivileges) | 
|  | 77 | { | 
|  | 78 | // If there are no privileges assigned, assume no privileges | 
|  | 79 | // required | 
|  | 80 | if (privilegesSet.empty()) | 
|  | 81 | { | 
|  | 82 | return true; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | for (const redfish::Privileges& requiredPrivileges : privilegesSet) | 
|  | 86 | { | 
|  | 87 | if (userPrivileges.isSupersetOf(requiredPrivileges)) | 
|  | 88 | { | 
|  | 89 | return true; | 
|  | 90 | } | 
|  | 91 | } | 
|  | 92 | return false; | 
|  | 93 | } | 
|  | 94 |  | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 95 | size_t methodsBitfield{ | 
|  | 96 | 1 << static_cast<size_t>(boost::beast::http::verb::get)}; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 97 |  | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 98 | std::vector<redfish::Privileges> privilegesSet; | 
|  | 99 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 100 | std::string rule; | 
|  | 101 | std::string nameStr; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 102 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 103 | std::unique_ptr<BaseRule> ruleToUpgrade; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 104 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 105 | friend class Router; | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 106 | template <typename T> | 
|  | 107 | friend struct RuleParameterTraits; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 108 | }; | 
|  | 109 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 110 | namespace detail | 
|  | 111 | { | 
|  | 112 | namespace routing_handler_call_helper | 
|  | 113 | { | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 114 | template <typename T, int Pos> | 
|  | 115 | struct CallPair | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 116 | { | 
|  | 117 | using type = T; | 
|  | 118 | static const int pos = Pos; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 119 | }; | 
|  | 120 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 121 | template <typename H1> | 
|  | 122 | struct CallParams | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 123 | { | 
|  | 124 | H1& handler; | 
|  | 125 | const RoutingParams& params; | 
|  | 126 | const Request& req; | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 127 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 128 | }; | 
|  | 129 |  | 
|  | 130 | template <typename F, int NInt, int NUint, int NDouble, int NString, | 
|  | 131 | typename S1, typename S2> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 132 | struct Call | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 133 | {}; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 134 |  | 
|  | 135 | template <typename F, int NInt, int NUint, int NDouble, int NString, | 
|  | 136 | typename... Args1, typename... Args2> | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 137 | struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<int64_t, Args1...>, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 138 | black_magic::S<Args2...>> | 
|  | 139 | { | 
|  | 140 | void operator()(F cparams) | 
|  | 141 | { | 
|  | 142 | using pushed = typename black_magic::S<Args2...>::template push_back< | 
|  | 143 | CallPair<int64_t, NInt>>; | 
|  | 144 | Call<F, NInt + 1, NUint, NDouble, NString, black_magic::S<Args1...>, | 
|  | 145 | pushed>()(cparams); | 
|  | 146 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 147 | }; | 
|  | 148 |  | 
|  | 149 | template <typename F, int NInt, int NUint, int NDouble, int NString, | 
|  | 150 | typename... Args1, typename... Args2> | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 151 | struct Call<F, NInt, NUint, NDouble, NString, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 152 | black_magic::S<uint64_t, Args1...>, black_magic::S<Args2...>> | 
|  | 153 | { | 
|  | 154 | void operator()(F cparams) | 
|  | 155 | { | 
|  | 156 | using pushed = typename black_magic::S<Args2...>::template push_back< | 
|  | 157 | CallPair<uint64_t, NUint>>; | 
|  | 158 | Call<F, NInt, NUint + 1, NDouble, NString, black_magic::S<Args1...>, | 
|  | 159 | pushed>()(cparams); | 
|  | 160 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 161 | }; | 
|  | 162 |  | 
|  | 163 | template <typename F, int NInt, int NUint, int NDouble, int NString, | 
|  | 164 | typename... Args1, typename... Args2> | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 165 | struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<double, Args1...>, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 166 | black_magic::S<Args2...>> | 
|  | 167 | { | 
|  | 168 | void operator()(F cparams) | 
|  | 169 | { | 
|  | 170 | using pushed = typename black_magic::S<Args2...>::template push_back< | 
|  | 171 | CallPair<double, NDouble>>; | 
|  | 172 | Call<F, NInt, NUint, NDouble + 1, NString, black_magic::S<Args1...>, | 
|  | 173 | pushed>()(cparams); | 
|  | 174 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 175 | }; | 
|  | 176 |  | 
|  | 177 | template <typename F, int NInt, int NUint, int NDouble, int NString, | 
|  | 178 | typename... Args1, typename... Args2> | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 179 | struct Call<F, NInt, NUint, NDouble, NString, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 180 | black_magic::S<std::string, Args1...>, black_magic::S<Args2...>> | 
|  | 181 | { | 
|  | 182 | void operator()(F cparams) | 
|  | 183 | { | 
|  | 184 | using pushed = typename black_magic::S<Args2...>::template push_back< | 
|  | 185 | CallPair<std::string, NString>>; | 
|  | 186 | Call<F, NInt, NUint, NDouble, NString + 1, black_magic::S<Args1...>, | 
|  | 187 | pushed>()(cparams); | 
|  | 188 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 189 | }; | 
|  | 190 |  | 
|  | 191 | template <typename F, int NInt, int NUint, int NDouble, int NString, | 
|  | 192 | typename... Args1> | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 193 | struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<>, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 194 | black_magic::S<Args1...>> | 
|  | 195 | { | 
|  | 196 | void operator()(F cparams) | 
|  | 197 | { | 
|  | 198 | cparams.handler( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 199 | cparams.req, cparams.asyncResp, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 200 | cparams.params.template get<typename Args1::type>(Args1::pos)...); | 
|  | 201 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 202 | }; | 
|  | 203 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 204 | template <typename Func, typename... ArgsWrapped> | 
|  | 205 | struct Wrapped | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 206 | { | 
|  | 207 | template <typename... Args> | 
|  | 208 | void set( | 
|  | 209 | Func f, | 
|  | 210 | typename std::enable_if< | 
|  | 211 | !std::is_same< | 
|  | 212 | typename std::tuple_element<0, std::tuple<Args..., void>>::type, | 
|  | 213 | const Request&>::value, | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 214 | int>::type /*enable*/ | 
|  | 215 | = 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 216 | { | 
| Ed Tanous | f94c4ec | 2022-01-06 12:44:41 -0800 | [diff] [blame] | 217 | handler = [f = std::forward<Func>(f)]( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 218 | const Request&, | 
|  | 219 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 220 | Args... args) { asyncResp->res.result(f(args...)); }; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 221 | } | 
|  | 222 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 223 | template <typename Req, typename... Args> | 
|  | 224 | struct ReqHandlerWrapper | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 225 | { | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 226 | ReqHandlerWrapper(Func fIn) : f(std::move(fIn)) | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 227 | {} | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 228 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 229 | void operator()(const Request& req, | 
|  | 230 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 231 | Args... args) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 232 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 233 | asyncResp->res.result(f(req, args...)); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 234 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 235 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 236 | Func f; | 
|  | 237 | }; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 238 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 239 | template <typename... Args> | 
|  | 240 | void set( | 
|  | 241 | Func f, | 
|  | 242 | typename std::enable_if< | 
|  | 243 | std::is_same< | 
|  | 244 | typename std::tuple_element<0, std::tuple<Args..., void>>::type, | 
|  | 245 | const Request&>::value && | 
|  | 246 | !std::is_same<typename std::tuple_element< | 
|  | 247 | 1, std::tuple<Args..., void, void>>::type, | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 248 | const std::shared_ptr<bmcweb::AsyncResp>&>::value, | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 249 | int>::type /*enable*/ | 
|  | 250 | = 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 251 | { | 
|  | 252 | handler = ReqHandlerWrapper<Args...>(std::move(f)); | 
|  | 253 | /*handler = ( | 
|  | 254 | [f = std::move(f)] | 
|  | 255 | (const Request& req, Response& res, Args... args){ | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 256 | res.result(f(req, args...)); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 257 | res.end(); | 
|  | 258 | });*/ | 
|  | 259 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 260 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 261 | template <typename... Args> | 
|  | 262 | void set( | 
|  | 263 | Func f, | 
|  | 264 | typename std::enable_if< | 
|  | 265 | std::is_same< | 
|  | 266 | typename std::tuple_element<0, std::tuple<Args..., void>>::type, | 
|  | 267 | const Request&>::value && | 
|  | 268 | std::is_same<typename std::tuple_element< | 
|  | 269 | 1, std::tuple<Args..., void, void>>::type, | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 270 | const std::shared_ptr<bmcweb::AsyncResp>&>::value, | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 271 | int>::type /*enable*/ | 
|  | 272 | = 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 273 | { | 
|  | 274 | handler = std::move(f); | 
|  | 275 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 276 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 277 | template <typename... Args> | 
|  | 278 | struct HandlerTypeHelper | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 279 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 280 | using type = std::function<void( | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 281 | const crow::Request& /*req*/, | 
|  | 282 | const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 283 | using args_type = | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 284 | black_magic::S<typename black_magic::PromoteT<Args>...>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 285 | }; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 286 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 287 | template <typename... Args> | 
|  | 288 | struct HandlerTypeHelper<const Request&, Args...> | 
|  | 289 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 290 | using type = std::function<void( | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 291 | const crow::Request& /*req*/, | 
|  | 292 | const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 293 | using args_type = | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 294 | black_magic::S<typename black_magic::PromoteT<Args>...>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 295 | }; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 296 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 297 | template <typename... Args> | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 298 | struct HandlerTypeHelper<const Request&, | 
|  | 299 | const std::shared_ptr<bmcweb::AsyncResp>&, Args...> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 300 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 301 | using type = std::function<void( | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 302 | const crow::Request& /*req*/, | 
|  | 303 | const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 304 | using args_type = | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 305 | black_magic::S<typename black_magic::PromoteT<Args>...>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 306 | }; | 
|  | 307 |  | 
|  | 308 | typename HandlerTypeHelper<ArgsWrapped...>::type handler; | 
|  | 309 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 310 | void operator()(const Request& req, | 
|  | 311 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 312 | const RoutingParams& params) | 
|  | 313 | { | 
|  | 314 | detail::routing_handler_call_helper::Call< | 
|  | 315 | detail::routing_handler_call_helper::CallParams<decltype(handler)>, | 
|  | 316 | 0, 0, 0, 0, typename HandlerTypeHelper<ArgsWrapped...>::args_type, | 
|  | 317 | black_magic::S<>>()( | 
|  | 318 | detail::routing_handler_call_helper::CallParams<decltype(handler)>{ | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 319 | handler, params, req, asyncResp}); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 320 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 321 | }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 322 | } // namespace routing_handler_call_helper | 
|  | 323 | } // namespace detail | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 324 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 325 | class WebSocketRule : public BaseRule | 
|  | 326 | { | 
|  | 327 | using self_t = WebSocketRule; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 328 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 329 | public: | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 330 | WebSocketRule(const std::string& ruleIn) : BaseRule(ruleIn) | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 331 | {} | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 332 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 333 | void validate() override | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 334 | {} | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 335 |  | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 336 | void handle(const Request& /*req*/, | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 337 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 338 | const RoutingParams& /*params*/) override | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 339 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 340 | asyncResp->res.result(boost::beast::http::status::not_found); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 341 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 342 |  | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 343 | void handleUpgrade(const Request& req, Response& /*res*/, | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 344 | boost::asio::ip::tcp::socket&& adaptor) override | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 345 | { | 
| Nan Zhou | 93c0202 | 2022-02-24 18:21:07 -0800 | [diff] [blame] | 346 | BMCWEB_LOG_DEBUG << "Websocket handles upgrade"; | 
| Ratan Gupta | 02453b1 | 2019-10-22 14:43:36 +0530 | [diff] [blame] | 347 | std::shared_ptr< | 
|  | 348 | crow::websocket::ConnectionImpl<boost::asio::ip::tcp::socket>> | 
|  | 349 | myConnection = std::make_shared< | 
|  | 350 | crow::websocket::ConnectionImpl<boost::asio::ip::tcp::socket>>( | 
| Jan Sowinski | ee52ae1 | 2020-01-09 16:28:32 +0000 | [diff] [blame] | 351 | req, std::move(adaptor), openHandler, messageHandler, | 
| Ratan Gupta | 02453b1 | 2019-10-22 14:43:36 +0530 | [diff] [blame] | 352 | closeHandler, errorHandler); | 
|  | 353 | myConnection->start(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 354 | } | 
|  | 355 | #ifdef BMCWEB_ENABLE_SSL | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 356 | void handleUpgrade(const Request& req, Response& /*res*/, | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 357 | boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&& | 
|  | 358 | adaptor) override | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 359 | { | 
| Nan Zhou | 93c0202 | 2022-02-24 18:21:07 -0800 | [diff] [blame] | 360 | BMCWEB_LOG_DEBUG << "Websocket handles upgrade"; | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 361 | std::shared_ptr<crow::websocket::ConnectionImpl< | 
|  | 362 | boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>> | 
|  | 363 | myConnection = std::make_shared<crow::websocket::ConnectionImpl< | 
|  | 364 | boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>>( | 
| Jan Sowinski | ee52ae1 | 2020-01-09 16:28:32 +0000 | [diff] [blame] | 365 | req, std::move(adaptor), openHandler, messageHandler, | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 366 | closeHandler, errorHandler); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 367 | myConnection->start(); | 
|  | 368 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 369 | #endif | 
|  | 370 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 371 | template <typename Func> | 
|  | 372 | self_t& onopen(Func f) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 373 | { | 
|  | 374 | openHandler = f; | 
|  | 375 | return *this; | 
|  | 376 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 377 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 378 | template <typename Func> | 
|  | 379 | self_t& onmessage(Func f) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 380 | { | 
|  | 381 | messageHandler = f; | 
|  | 382 | return *this; | 
|  | 383 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 384 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 385 | template <typename Func> | 
|  | 386 | self_t& onclose(Func f) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 387 | { | 
|  | 388 | closeHandler = f; | 
|  | 389 | return *this; | 
|  | 390 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 391 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 392 | template <typename Func> | 
|  | 393 | self_t& onerror(Func f) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 394 | { | 
|  | 395 | errorHandler = f; | 
|  | 396 | return *this; | 
|  | 397 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 398 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 399 | protected: | 
| zhanghch05 | 7772638 | 2021-10-21 14:07:57 +0800 | [diff] [blame^] | 400 | std::function<void(crow::websocket::Connection&)> openHandler; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 401 | std::function<void(crow::websocket::Connection&, const std::string&, bool)> | 
|  | 402 | messageHandler; | 
|  | 403 | std::function<void(crow::websocket::Connection&, const std::string&)> | 
|  | 404 | closeHandler; | 
|  | 405 | std::function<void(crow::websocket::Connection&)> errorHandler; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 406 | }; | 
|  | 407 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 408 | template <typename T> | 
|  | 409 | struct RuleParameterTraits | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 410 | { | 
|  | 411 | using self_t = T; | 
|  | 412 | WebSocketRule& websocket() | 
|  | 413 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 414 | self_t* self = static_cast<self_t*>(this); | 
|  | 415 | WebSocketRule* p = new WebSocketRule(self->rule); | 
|  | 416 | self->ruleToUpgrade.reset(p); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 417 | return *p; | 
|  | 418 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 419 |  | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 420 | self_t& name(const std::string_view name) noexcept | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 421 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 422 | self_t* self = static_cast<self_t*>(this); | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 423 | self->nameStr = name; | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 424 | return *self; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 425 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 426 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 427 | self_t& methods(boost::beast::http::verb method) | 
|  | 428 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 429 | self_t* self = static_cast<self_t*>(this); | 
|  | 430 | self->methodsBitfield = 1U << static_cast<size_t>(method); | 
|  | 431 | return *self; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 432 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 433 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 434 | template <typename... MethodArgs> | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 435 | self_t& methods(boost::beast::http::verb method, MethodArgs... argsMethod) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 436 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 437 | self_t* self = static_cast<self_t*>(this); | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 438 | methods(argsMethod...); | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 439 | self->methodsBitfield |= 1U << static_cast<size_t>(method); | 
|  | 440 | return *self; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 441 | } | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 442 |  | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 443 | self_t& privileges( | 
|  | 444 | const std::initializer_list<std::initializer_list<const char*>>& p) | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 445 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 446 | self_t* self = static_cast<self_t*>(this); | 
| Ed Tanous | 432a890 | 2021-06-14 15:28:56 -0700 | [diff] [blame] | 447 | for (const std::initializer_list<const char*>& privilege : p) | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 448 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 449 | self->privilegesSet.emplace_back(privilege); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 450 | } | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 451 | return *self; | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 452 | } | 
| Ed Tanous | ed39821 | 2021-06-09 17:05:54 -0700 | [diff] [blame] | 453 |  | 
|  | 454 | template <size_t N, typename... MethodArgs> | 
|  | 455 | self_t& privileges(const std::array<redfish::Privileges, N>& p) | 
|  | 456 | { | 
|  | 457 | self_t* self = static_cast<self_t*>(this); | 
|  | 458 | for (const redfish::Privileges& privilege : p) | 
|  | 459 | { | 
|  | 460 | self->privilegesSet.emplace_back(privilege); | 
|  | 461 | } | 
|  | 462 | return *self; | 
|  | 463 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 464 | }; | 
|  | 465 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 466 | class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> | 
|  | 467 | { | 
|  | 468 | public: | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 469 | DynamicRule(const std::string& ruleIn) : BaseRule(ruleIn) | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 470 | {} | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 471 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 472 | void validate() override | 
|  | 473 | { | 
|  | 474 | if (!erasedHandler) | 
|  | 475 | { | 
|  | 476 | throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") + | 
|  | 477 | "no handler for url " + rule); | 
|  | 478 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 479 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 480 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 481 | void handle(const Request& req, | 
|  | 482 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 483 | const RoutingParams& params) override | 
|  | 484 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 485 | erasedHandler(req, asyncResp, params); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 486 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 487 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 488 | template <typename Func> | 
|  | 489 | void operator()(Func f) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 490 | { | 
|  | 491 | using function_t = utility::function_traits<Func>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 492 | erasedHandler = | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 493 | wrap(std::move(f), | 
|  | 494 | std::make_integer_sequence<unsigned, function_t::arity>{}); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 495 | } | 
|  | 496 |  | 
|  | 497 | // enable_if Arg1 == request && Arg2 == Response | 
| Gunnar Mills | 6be0e40 | 2020-07-08 13:21:51 -0500 | [diff] [blame] | 498 | // enable_if Arg1 == request && Arg2 != response | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 499 | // enable_if Arg1 != request | 
|  | 500 |  | 
|  | 501 | template <typename Func, unsigned... Indices> | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 502 | std::function<void(const Request&, | 
|  | 503 | const std::shared_ptr<bmcweb::AsyncResp>&, | 
|  | 504 | const RoutingParams&)> | 
| Ed Tanous | 104f09c | 2022-01-25 09:56:04 -0800 | [diff] [blame] | 505 | wrap(Func f, std::integer_sequence<unsigned, Indices...> /*is*/) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 506 | { | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 507 | using function_t = crow::utility::function_traits<Func>; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 508 |  | 
|  | 509 | if (!black_magic::isParameterTagCompatible( | 
| Ed Tanous | 988403c | 2020-08-24 11:29:49 -0700 | [diff] [blame] | 510 | black_magic::getParameterTag(rule.c_str()), | 
|  | 511 | black_magic::computeParameterTagFromArgsList< | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 512 | typename function_t::template arg<Indices>...>::value)) | 
|  | 513 | { | 
|  | 514 | throw std::runtime_error("routeDynamic: Handler type is mismatched " | 
|  | 515 | "with URL parameters: " + | 
|  | 516 | rule); | 
|  | 517 | } | 
|  | 518 | auto ret = detail::routing_handler_call_helper::Wrapped< | 
|  | 519 | Func, typename function_t::template arg<Indices>...>(); | 
|  | 520 | ret.template set<typename function_t::template arg<Indices>...>( | 
|  | 521 | std::move(f)); | 
|  | 522 | return ret; | 
|  | 523 | } | 
|  | 524 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 525 | template <typename Func> | 
|  | 526 | void operator()(std::string name, Func&& f) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 527 | { | 
|  | 528 | nameStr = std::move(name); | 
|  | 529 | (*this).template operator()<Func>(std::forward(f)); | 
|  | 530 | } | 
|  | 531 |  | 
|  | 532 | private: | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 533 | std::function<void(const Request&, | 
|  | 534 | const std::shared_ptr<bmcweb::AsyncResp>&, | 
|  | 535 | const RoutingParams&)> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 536 | erasedHandler; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 537 | }; | 
|  | 538 |  | 
|  | 539 | template <typename... Args> | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 540 | class TaggedRule : | 
|  | 541 | public BaseRule, | 
|  | 542 | public RuleParameterTraits<TaggedRule<Args...>> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 543 | { | 
|  | 544 | public: | 
|  | 545 | using self_t = TaggedRule<Args...>; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 546 |  | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 547 | TaggedRule(const std::string& ruleIn) : BaseRule(ruleIn) | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 548 | {} | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 549 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 550 | void validate() override | 
|  | 551 | { | 
|  | 552 | if (!handler) | 
|  | 553 | { | 
|  | 554 | throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") + | 
|  | 555 | "no handler for url " + rule); | 
|  | 556 | } | 
|  | 557 | } | 
|  | 558 |  | 
|  | 559 | template <typename Func> | 
|  | 560 | typename std::enable_if< | 
|  | 561 | black_magic::CallHelper<Func, black_magic::S<Args...>>::value, | 
|  | 562 | void>::type | 
|  | 563 | operator()(Func&& f) | 
|  | 564 | { | 
|  | 565 | static_assert( | 
|  | 566 | black_magic::CallHelper<Func, black_magic::S<Args...>>::value || | 
|  | 567 | black_magic::CallHelper< | 
|  | 568 | Func, black_magic::S<crow::Request, Args...>>::value, | 
|  | 569 | "Handler type is mismatched with URL parameters"); | 
|  | 570 | static_assert( | 
|  | 571 | !std::is_same<void, decltype(f(std::declval<Args>()...))>::value, | 
|  | 572 | "Handler function cannot have void return type; valid return " | 
|  | 573 | "types: " | 
| Gunnar Mills | 6be0e40 | 2020-07-08 13:21:51 -0500 | [diff] [blame] | 574 | "string, int, crow::response, nlohmann::json"); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 575 |  | 
| Ed Tanous | f94c4ec | 2022-01-06 12:44:41 -0800 | [diff] [blame] | 576 | handler = [f = std::forward<Func>(f)]( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 577 | const Request&, | 
|  | 578 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 579 | Args... args) { asyncResp->res.result(f(args...)); }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 580 | } | 
|  | 581 |  | 
|  | 582 | template <typename Func> | 
|  | 583 | typename std::enable_if< | 
|  | 584 | !black_magic::CallHelper<Func, black_magic::S<Args...>>::value && | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 585 | black_magic::CallHelper< | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 586 | Func, black_magic::S<crow::Request, Args...>>::value, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 587 | void>::type | 
|  | 588 | operator()(Func&& f) | 
|  | 589 | { | 
|  | 590 | static_assert( | 
|  | 591 | black_magic::CallHelper<Func, black_magic::S<Args...>>::value || | 
|  | 592 | black_magic::CallHelper< | 
|  | 593 | Func, black_magic::S<crow::Request, Args...>>::value, | 
|  | 594 | "Handler type is mismatched with URL parameters"); | 
|  | 595 | static_assert( | 
|  | 596 | !std::is_same<void, decltype(f(std::declval<crow::Request>(), | 
|  | 597 | std::declval<Args>()...))>::value, | 
|  | 598 | "Handler function cannot have void return type; valid return " | 
|  | 599 | "types: " | 
| Gunnar Mills | 6be0e40 | 2020-07-08 13:21:51 -0500 | [diff] [blame] | 600 | "string, int, crow::response,nlohmann::json"); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 601 |  | 
| Ed Tanous | f94c4ec | 2022-01-06 12:44:41 -0800 | [diff] [blame] | 602 | handler = [f = std::forward<Func>(f)]( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 603 | const crow::Request& req, | 
|  | 604 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 605 | Args... args) { asyncResp->res.result(f(req, args...)); }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 606 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 607 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 608 | template <typename Func> | 
|  | 609 | typename std::enable_if< | 
|  | 610 | !black_magic::CallHelper<Func, black_magic::S<Args...>>::value && | 
|  | 611 | !black_magic::CallHelper< | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 612 | Func, black_magic::S<crow::Request, Args...>>::value, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 613 | void>::type | 
|  | 614 | operator()(Func&& f) | 
|  | 615 | { | 
|  | 616 | static_assert( | 
|  | 617 | black_magic::CallHelper<Func, black_magic::S<Args...>>::value || | 
|  | 618 | black_magic::CallHelper< | 
|  | 619 | Func, black_magic::S<crow::Request, Args...>>::value || | 
|  | 620 | black_magic::CallHelper< | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 621 | Func, black_magic::S<crow::Request, | 
|  | 622 | std::shared_ptr<bmcweb::AsyncResp>&, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 623 | Args...>>::value, | 
|  | 624 | "Handler type is mismatched with URL parameters"); | 
|  | 625 | static_assert( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 626 | std::is_same< | 
|  | 627 | void, | 
|  | 628 | decltype(f(std::declval<crow::Request>(), | 
|  | 629 | std::declval<std::shared_ptr<bmcweb::AsyncResp>&>(), | 
|  | 630 | std::declval<Args>()...))>::value, | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 631 | "Handler function with response argument should have void " | 
|  | 632 | "return " | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 633 | "type"); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 634 |  | 
| Ed Tanous | f94c4ec | 2022-01-06 12:44:41 -0800 | [diff] [blame] | 635 | handler = std::forward<Func>(f); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 636 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 637 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 638 | template <typename Func> | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 639 | void operator()(const std::string_view name, Func&& f) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 640 | { | 
| Ed Tanous | f23b729 | 2020-10-15 09:41:17 -0700 | [diff] [blame] | 641 | nameStr = name; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 642 | (*this).template operator()<Func>(std::forward(f)); | 
|  | 643 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 644 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 645 | void handle(const Request& req, | 
|  | 646 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 647 | const RoutingParams& params) override | 
|  | 648 | { | 
|  | 649 | detail::routing_handler_call_helper::Call< | 
|  | 650 | detail::routing_handler_call_helper::CallParams<decltype(handler)>, | 
|  | 651 | 0, 0, 0, 0, black_magic::S<Args...>, black_magic::S<>>()( | 
|  | 652 | detail::routing_handler_call_helper::CallParams<decltype(handler)>{ | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 653 | handler, params, req, asyncResp}); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 654 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 655 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 656 | private: | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 657 | std::function<void(const crow::Request&, | 
|  | 658 | const std::shared_ptr<bmcweb::AsyncResp>&, Args...)> | 
|  | 659 | handler; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 660 | }; | 
|  | 661 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 662 | class Trie | 
|  | 663 | { | 
|  | 664 | public: | 
|  | 665 | struct Node | 
|  | 666 | { | 
|  | 667 | unsigned ruleIndex{}; | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 668 | std::array<size_t, static_cast<size_t>(ParamType::MAX)> | 
|  | 669 | paramChildrens{}; | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 670 | using ChildMap = boost::container::flat_map< | 
|  | 671 | std::string, unsigned, std::less<>, | 
|  | 672 | std::vector<std::pair<std::string, unsigned>>>; | 
|  | 673 | ChildMap children; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 674 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 675 | bool isSimpleNode() const | 
|  | 676 | { | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 677 | return ruleIndex == 0 && | 
|  | 678 | std::all_of(std::begin(paramChildrens), | 
|  | 679 | std::end(paramChildrens), | 
|  | 680 | [](size_t x) { return x == 0U; }); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 681 | } | 
| Ed Tanous | 55c7b7a | 2018-05-22 15:27:24 -0700 | [diff] [blame] | 682 | }; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 683 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 684 | Trie() : nodes(1) | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 685 | {} | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 686 |  | 
|  | 687 | private: | 
|  | 688 | void optimizeNode(Node* node) | 
|  | 689 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 690 | for (size_t x : node->paramChildrens) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 691 | { | 
| Ed Tanous | dbb59d4 | 2022-01-25 11:09:55 -0800 | [diff] [blame] | 692 | if (x == 0U) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 693 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 694 | continue; | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 695 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 696 | Node* child = &nodes[x]; | 
|  | 697 | optimizeNode(child); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 698 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 699 | if (node->children.empty()) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 700 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 701 | return; | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 702 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 703 | bool mergeWithChild = true; | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 704 | for (const Node::ChildMap::value_type& kv : node->children) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 705 | { | 
|  | 706 | Node* child = &nodes[kv.second]; | 
|  | 707 | if (!child->isSimpleNode()) | 
|  | 708 | { | 
|  | 709 | mergeWithChild = false; | 
|  | 710 | break; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 711 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 712 | } | 
|  | 713 | if (mergeWithChild) | 
|  | 714 | { | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 715 | Node::ChildMap merged; | 
|  | 716 | for (const Node::ChildMap::value_type& kv : node->children) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 717 | { | 
|  | 718 | Node* child = &nodes[kv.second]; | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 719 | for (const Node::ChildMap::value_type& childKv : | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 720 | child->children) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 721 | { | 
|  | 722 | merged[kv.first + childKv.first] = childKv.second; | 
|  | 723 | } | 
|  | 724 | } | 
|  | 725 | node->children = std::move(merged); | 
|  | 726 | optimizeNode(node); | 
|  | 727 | } | 
|  | 728 | else | 
|  | 729 | { | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 730 | for (const Node::ChildMap::value_type& kv : node->children) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 731 | { | 
|  | 732 | Node* child = &nodes[kv.second]; | 
|  | 733 | optimizeNode(child); | 
|  | 734 | } | 
|  | 735 | } | 
|  | 736 | } | 
|  | 737 |  | 
|  | 738 | void optimize() | 
|  | 739 | { | 
|  | 740 | optimizeNode(head()); | 
|  | 741 | } | 
|  | 742 |  | 
|  | 743 | public: | 
|  | 744 | void validate() | 
|  | 745 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 746 | optimize(); | 
|  | 747 | } | 
|  | 748 |  | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 749 | void findRouteIndexes(const std::string& reqUrl, | 
|  | 750 | std::vector<unsigned>& routeIndexes, | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 751 | const Node* node = nullptr, unsigned pos = 0) const | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 752 | { | 
|  | 753 | if (node == nullptr) | 
|  | 754 | { | 
|  | 755 | node = head(); | 
|  | 756 | } | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 757 | for (const Node::ChildMap::value_type& kv : node->children) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 758 | { | 
|  | 759 | const std::string& fragment = kv.first; | 
|  | 760 | const Node* child = &nodes[kv.second]; | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 761 | if (pos >= reqUrl.size()) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 762 | { | 
|  | 763 | if (child->ruleIndex != 0 && fragment != "/") | 
|  | 764 | { | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 765 | routeIndexes.push_back(child->ruleIndex); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 766 | } | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 767 | findRouteIndexes(reqUrl, routeIndexes, child, | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 768 | static_cast<unsigned>(pos + fragment.size())); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 769 | } | 
|  | 770 | else | 
|  | 771 | { | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 772 | if (reqUrl.compare(pos, fragment.size(), fragment) == 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 773 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 774 | findRouteIndexes( | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 775 | reqUrl, routeIndexes, child, | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 776 | static_cast<unsigned>(pos + fragment.size())); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 777 | } | 
|  | 778 | } | 
|  | 779 | } | 
|  | 780 | } | 
|  | 781 |  | 
|  | 782 | std::pair<unsigned, RoutingParams> | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 783 | find(const std::string_view reqUrl, const Node* node = nullptr, | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 784 | size_t pos = 0, RoutingParams* params = nullptr) const | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 785 | { | 
|  | 786 | RoutingParams empty; | 
|  | 787 | if (params == nullptr) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 788 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 789 | params = ∅ | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 790 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 791 |  | 
|  | 792 | unsigned found{}; | 
|  | 793 | RoutingParams matchParams; | 
|  | 794 |  | 
|  | 795 | if (node == nullptr) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 796 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 797 | node = head(); | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 798 | } | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 799 | if (pos == reqUrl.size()) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 800 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 801 | return {node->ruleIndex, *params}; | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 802 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 803 |  | 
|  | 804 | auto updateFound = | 
|  | 805 | [&found, &matchParams](std::pair<unsigned, RoutingParams>& ret) { | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 806 | if (ret.first != 0U && (found == 0U || found > ret.first)) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 807 | { | 
|  | 808 | found = ret.first; | 
|  | 809 | matchParams = std::move(ret.second); | 
|  | 810 | } | 
|  | 811 | }; | 
|  | 812 |  | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 813 | if (node->paramChildrens[static_cast<size_t>(ParamType::INT)] != 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 814 | { | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 815 | char c = reqUrl[pos]; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 816 | if ((c >= '0' && c <= '9') || c == '+' || c == '-') | 
|  | 817 | { | 
| Ed Tanous | 543f440 | 2022-01-06 13:12:53 -0800 | [diff] [blame] | 818 | char* eptr = nullptr; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 819 | errno = 0; | 
|  | 820 | long long int value = | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 821 | std::strtoll(reqUrl.data() + pos, &eptr, 10); | 
|  | 822 | if (errno != ERANGE && eptr != reqUrl.data() + pos) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 823 | { | 
|  | 824 | params->intParams.push_back(value); | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 825 | std::pair<unsigned, RoutingParams> ret = | 
|  | 826 | find(reqUrl, | 
|  | 827 | &nodes[node->paramChildrens[static_cast<size_t>( | 
|  | 828 | ParamType::INT)]], | 
|  | 829 | static_cast<size_t>(eptr - reqUrl.data()), params); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 830 | updateFound(ret); | 
|  | 831 | params->intParams.pop_back(); | 
|  | 832 | } | 
|  | 833 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 834 | } | 
|  | 835 |  | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 836 | if (node->paramChildrens[static_cast<size_t>(ParamType::UINT)] != 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 837 | { | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 838 | char c = reqUrl[pos]; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 839 | if ((c >= '0' && c <= '9') || c == '+') | 
|  | 840 | { | 
| Ed Tanous | 543f440 | 2022-01-06 13:12:53 -0800 | [diff] [blame] | 841 | char* eptr = nullptr; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 842 | errno = 0; | 
|  | 843 | unsigned long long int value = | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 844 | std::strtoull(reqUrl.data() + pos, &eptr, 10); | 
|  | 845 | if (errno != ERANGE && eptr != reqUrl.data() + pos) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 846 | { | 
|  | 847 | params->uintParams.push_back(value); | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 848 | std::pair<unsigned, RoutingParams> ret = | 
|  | 849 | find(reqUrl, | 
|  | 850 | &nodes[node->paramChildrens[static_cast<size_t>( | 
|  | 851 | ParamType::UINT)]], | 
|  | 852 | static_cast<size_t>(eptr - reqUrl.data()), params); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 853 | updateFound(ret); | 
|  | 854 | params->uintParams.pop_back(); | 
|  | 855 | } | 
|  | 856 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 857 | } | 
|  | 858 |  | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 859 | if (node->paramChildrens[static_cast<size_t>(ParamType::DOUBLE)] != 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 860 | { | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 861 | char c = reqUrl[pos]; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 862 | if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.') | 
|  | 863 | { | 
| Ed Tanous | 543f440 | 2022-01-06 13:12:53 -0800 | [diff] [blame] | 864 | char* eptr = nullptr; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 865 | errno = 0; | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 866 | double value = std::strtod(reqUrl.data() + pos, &eptr); | 
|  | 867 | if (errno != ERANGE && eptr != reqUrl.data() + pos) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 868 | { | 
|  | 869 | params->doubleParams.push_back(value); | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 870 | std::pair<unsigned, RoutingParams> ret = | 
|  | 871 | find(reqUrl, | 
|  | 872 | &nodes[node->paramChildrens[static_cast<size_t>( | 
|  | 873 | ParamType::DOUBLE)]], | 
|  | 874 | static_cast<size_t>(eptr - reqUrl.data()), params); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 875 | updateFound(ret); | 
|  | 876 | params->doubleParams.pop_back(); | 
|  | 877 | } | 
|  | 878 | } | 
|  | 879 | } | 
|  | 880 |  | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 881 | if (node->paramChildrens[static_cast<size_t>(ParamType::STRING)] != 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 882 | { | 
| Ed Tanous | b01bf29 | 2019-03-25 19:25:26 +0000 | [diff] [blame] | 883 | size_t epos = pos; | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 884 | for (; epos < reqUrl.size(); epos++) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 885 | { | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 886 | if (reqUrl[epos] == '/') | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 887 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 888 | break; | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 889 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 890 | } | 
|  | 891 |  | 
|  | 892 | if (epos != pos) | 
|  | 893 | { | 
|  | 894 | params->stringParams.emplace_back( | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 895 | reqUrl.substr(pos, epos - pos)); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 896 | std::pair<unsigned, RoutingParams> ret = | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 897 | find(reqUrl, | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 898 | &nodes[node->paramChildrens[static_cast<size_t>( | 
|  | 899 | ParamType::STRING)]], | 
| Ed Tanous | b01bf29 | 2019-03-25 19:25:26 +0000 | [diff] [blame] | 900 | epos, params); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 901 | updateFound(ret); | 
|  | 902 | params->stringParams.pop_back(); | 
|  | 903 | } | 
|  | 904 | } | 
|  | 905 |  | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 906 | if (node->paramChildrens[static_cast<size_t>(ParamType::PATH)] != 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 907 | { | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 908 | size_t epos = reqUrl.size(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 909 |  | 
|  | 910 | if (epos != pos) | 
|  | 911 | { | 
|  | 912 | params->stringParams.emplace_back( | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 913 | reqUrl.substr(pos, epos - pos)); | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 914 | std::pair<unsigned, RoutingParams> ret = | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 915 | find(reqUrl, | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 916 | &nodes[node->paramChildrens[static_cast<size_t>( | 
|  | 917 | ParamType::PATH)]], | 
|  | 918 | epos, params); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 919 | updateFound(ret); | 
|  | 920 | params->stringParams.pop_back(); | 
|  | 921 | } | 
|  | 922 | } | 
|  | 923 |  | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 924 | for (const Node::ChildMap::value_type& kv : node->children) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 925 | { | 
|  | 926 | const std::string& fragment = kv.first; | 
|  | 927 | const Node* child = &nodes[kv.second]; | 
|  | 928 |  | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 929 | if (reqUrl.compare(pos, fragment.size(), fragment) == 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 930 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 931 | std::pair<unsigned, RoutingParams> ret = | 
| Ed Tanous | 81ce609 | 2020-12-17 16:54:55 +0000 | [diff] [blame] | 932 | find(reqUrl, child, pos + fragment.size(), params); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 933 | updateFound(ret); | 
|  | 934 | } | 
|  | 935 | } | 
|  | 936 |  | 
|  | 937 | return {found, matchParams}; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 938 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 939 |  | 
|  | 940 | void add(const std::string& url, unsigned ruleIndex) | 
|  | 941 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 942 | size_t idx = 0; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 943 |  | 
|  | 944 | for (unsigned i = 0; i < url.size(); i++) | 
|  | 945 | { | 
|  | 946 | char c = url[i]; | 
|  | 947 | if (c == '<') | 
|  | 948 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 949 | const static std::array<std::pair<ParamType, std::string>, 7> | 
|  | 950 | paramTraits = {{ | 
|  | 951 | {ParamType::INT, "<int>"}, | 
|  | 952 | {ParamType::UINT, "<uint>"}, | 
|  | 953 | {ParamType::DOUBLE, "<float>"}, | 
|  | 954 | {ParamType::DOUBLE, "<double>"}, | 
|  | 955 | {ParamType::STRING, "<str>"}, | 
|  | 956 | {ParamType::STRING, "<string>"}, | 
|  | 957 | {ParamType::PATH, "<path>"}, | 
|  | 958 | }}; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 959 |  | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 960 | for (const std::pair<ParamType, std::string>& x : paramTraits) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 961 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 962 | if (url.compare(i, x.second.size(), x.second) == 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 963 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 964 | size_t index = static_cast<size_t>(x.first); | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 965 | if (nodes[idx].paramChildrens[index] == 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 966 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 967 | unsigned newNodeIdx = newNode(); | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 968 | nodes[idx].paramChildrens[index] = newNodeIdx; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 969 | } | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 970 | idx = nodes[idx].paramChildrens[index]; | 
|  | 971 | i += static_cast<unsigned>(x.second.size()); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 972 | break; | 
|  | 973 | } | 
|  | 974 | } | 
|  | 975 |  | 
|  | 976 | i--; | 
|  | 977 | } | 
|  | 978 | else | 
|  | 979 | { | 
|  | 980 | std::string piece(&c, 1); | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 981 | if (nodes[idx].children.count(piece) == 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 982 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 983 | unsigned newNodeIdx = newNode(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 984 | nodes[idx].children.emplace(piece, newNodeIdx); | 
|  | 985 | } | 
|  | 986 | idx = nodes[idx].children[piece]; | 
|  | 987 | } | 
|  | 988 | } | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 989 | if (nodes[idx].ruleIndex != 0U) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 990 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 991 | throw std::runtime_error("handler already exists for " + url); | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 992 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 993 | nodes[idx].ruleIndex = ruleIndex; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 994 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 995 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 996 | private: | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 997 | void debugNodePrint(Node* n, size_t level) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 998 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 999 | for (size_t i = 0; i < static_cast<size_t>(ParamType::MAX); i++) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1000 | { | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 1001 | if (n->paramChildrens[i] != 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1002 | { | 
|  | 1003 | BMCWEB_LOG_DEBUG << std::string( | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1004 | 2U * level, ' ') /*<< "("<<n->paramChildrens[i]<<") "*/; | 
|  | 1005 | switch (static_cast<ParamType>(i)) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1006 | { | 
|  | 1007 | case ParamType::INT: | 
|  | 1008 | BMCWEB_LOG_DEBUG << "<int>"; | 
|  | 1009 | break; | 
|  | 1010 | case ParamType::UINT: | 
|  | 1011 | BMCWEB_LOG_DEBUG << "<uint>"; | 
|  | 1012 | break; | 
|  | 1013 | case ParamType::DOUBLE: | 
|  | 1014 | BMCWEB_LOG_DEBUG << "<float>"; | 
|  | 1015 | break; | 
|  | 1016 | case ParamType::STRING: | 
|  | 1017 | BMCWEB_LOG_DEBUG << "<str>"; | 
|  | 1018 | break; | 
|  | 1019 | case ParamType::PATH: | 
|  | 1020 | BMCWEB_LOG_DEBUG << "<path>"; | 
|  | 1021 | break; | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1022 | case ParamType::MAX: | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1023 | BMCWEB_LOG_DEBUG << "<ERROR>"; | 
|  | 1024 | break; | 
|  | 1025 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1026 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1027 | debugNodePrint(&nodes[n->paramChildrens[i]], level + 1); | 
|  | 1028 | } | 
|  | 1029 | } | 
| Ed Tanous | a94ac61 | 2022-02-22 11:13:24 -0800 | [diff] [blame] | 1030 | for (const Node::ChildMap::value_type& kv : n->children) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1031 | { | 
|  | 1032 | BMCWEB_LOG_DEBUG | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1033 | << std::string(2U * level, ' ') /*<< "(" << kv.second << ") "*/ | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1034 | << kv.first; | 
|  | 1035 | debugNodePrint(&nodes[kv.second], level + 1); | 
|  | 1036 | } | 
|  | 1037 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1038 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1039 | public: | 
|  | 1040 | void debugPrint() | 
|  | 1041 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1042 | debugNodePrint(head(), 0U); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1043 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1044 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1045 | private: | 
|  | 1046 | const Node* head() const | 
|  | 1047 | { | 
|  | 1048 | return &nodes.front(); | 
|  | 1049 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1050 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1051 | Node* head() | 
|  | 1052 | { | 
|  | 1053 | return &nodes.front(); | 
|  | 1054 | } | 
|  | 1055 |  | 
|  | 1056 | unsigned newNode() | 
|  | 1057 | { | 
|  | 1058 | nodes.resize(nodes.size() + 1); | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1059 | return static_cast<unsigned>(nodes.size() - 1); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1060 | } | 
|  | 1061 |  | 
|  | 1062 | std::vector<Node> nodes; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1063 | }; | 
|  | 1064 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1065 | class Router | 
|  | 1066 | { | 
|  | 1067 | public: | 
| Ed Tanous | 0c0084a | 2019-10-24 15:57:51 -0700 | [diff] [blame] | 1068 | Router() = default; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1069 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1070 | DynamicRule& newRuleDynamic(const std::string& rule) | 
|  | 1071 | { | 
|  | 1072 | std::unique_ptr<DynamicRule> ruleObject = | 
|  | 1073 | std::make_unique<DynamicRule>(rule); | 
|  | 1074 | DynamicRule* ptr = ruleObject.get(); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1075 | allRules.emplace_back(std::move(ruleObject)); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1076 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1077 | return *ptr; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1078 | } | 
|  | 1079 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1080 | template <uint64_t N> | 
|  | 1081 | typename black_magic::Arguments<N>::type::template rebind<TaggedRule>& | 
|  | 1082 | newRuleTagged(const std::string& rule) | 
|  | 1083 | { | 
|  | 1084 | using RuleT = typename black_magic::Arguments<N>::type::template rebind< | 
|  | 1085 | TaggedRule>; | 
|  | 1086 | std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule); | 
|  | 1087 | RuleT* ptr = ruleObject.get(); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1088 | allRules.emplace_back(std::move(ruleObject)); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1089 |  | 
|  | 1090 | return *ptr; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1091 | } | 
|  | 1092 |  | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1093 | void internalAddRuleObject(const std::string& rule, BaseRule* ruleObject) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1094 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1095 | if (ruleObject == nullptr) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1096 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1097 | return; | 
|  | 1098 | } | 
| Ed Tanous | 888880a | 2020-08-24 13:48:50 -0700 | [diff] [blame] | 1099 | for (size_t method = 0, methodBit = 1; method < maxHttpVerbCount; | 
| Ed Tanous | 2c70f80 | 2020-09-28 14:29:23 -0700 | [diff] [blame] | 1100 | method++, methodBit <<= 1) | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1101 | { | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 1102 | if ((ruleObject->methodsBitfield & methodBit) > 0U) | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1103 | { | 
|  | 1104 | perMethods[method].rules.emplace_back(ruleObject); | 
|  | 1105 | perMethods[method].trie.add( | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1106 | rule, static_cast<unsigned>( | 
|  | 1107 | perMethods[method].rules.size() - 1U)); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1108 | // directory case: | 
|  | 1109 | //   request to `/about' url matches `/about/' rule | 
|  | 1110 | if (rule.size() > 2 && rule.back() == '/') | 
|  | 1111 | { | 
|  | 1112 | perMethods[method].trie.add( | 
|  | 1113 | rule.substr(0, rule.size() - 1), | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1114 | static_cast<unsigned>(perMethods[method].rules.size() - | 
|  | 1115 | 1)); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1116 | } | 
|  | 1117 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1118 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1119 | } | 
|  | 1120 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1121 | void validate() | 
|  | 1122 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1123 | for (std::unique_ptr<BaseRule>& rule : allRules) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1124 | { | 
|  | 1125 | if (rule) | 
|  | 1126 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1127 | std::unique_ptr<BaseRule> upgraded = rule->upgrade(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1128 | if (upgraded) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 1129 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1130 | rule = std::move(upgraded); | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 1131 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1132 | rule->validate(); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1133 | internalAddRuleObject(rule->rule, rule.get()); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1134 | } | 
|  | 1135 | } | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1136 | for (PerMethod& perMethod : perMethods) | 
|  | 1137 | { | 
|  | 1138 | perMethod.trie.validate(); | 
|  | 1139 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1140 | } | 
|  | 1141 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1142 | template <typename Adaptor> | 
|  | 1143 | void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor) | 
|  | 1144 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1145 | if (static_cast<size_t>(req.method()) >= perMethods.size()) | 
| Ed Tanous | 888880a | 2020-08-24 13:48:50 -0700 | [diff] [blame] | 1146 | { | 
|  | 1147 | res.result(boost::beast::http::status::not_found); | 
|  | 1148 | res.end(); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1149 | return; | 
| Ed Tanous | 888880a | 2020-08-24 13:48:50 -0700 | [diff] [blame] | 1150 | } | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1151 |  | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1152 | PerMethod& perMethod = perMethods[static_cast<size_t>(req.method())]; | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1153 | Trie& trie = perMethod.trie; | 
|  | 1154 | std::vector<BaseRule*>& rules = perMethod.rules; | 
|  | 1155 |  | 
|  | 1156 | const std::pair<unsigned, RoutingParams>& found = trie.find(req.url); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1157 | unsigned ruleIndex = found.first; | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 1158 | if (ruleIndex == 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1159 | { | 
|  | 1160 | BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url; | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 1161 | res.result(boost::beast::http::status::not_found); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1162 | res.end(); | 
|  | 1163 | return; | 
|  | 1164 | } | 
|  | 1165 |  | 
|  | 1166 | if (ruleIndex >= rules.size()) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 1167 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1168 | throw std::runtime_error("Trie internal structure corrupted!"); | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 1169 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1170 |  | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1171 | if ((rules[ruleIndex]->getMethods() & | 
|  | 1172 | (1U << static_cast<size_t>(req.method()))) == 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1173 | { | 
|  | 1174 | BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url | 
|  | 1175 | << " with " << req.methodString() << "(" | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1176 | << static_cast<uint32_t>(req.method()) << ") / " | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1177 | << rules[ruleIndex]->getMethods(); | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 1178 | res.result(boost::beast::http::status::not_found); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1179 | res.end(); | 
|  | 1180 | return; | 
|  | 1181 | } | 
|  | 1182 |  | 
|  | 1183 | BMCWEB_LOG_DEBUG << "Matched rule (upgrade) '" << rules[ruleIndex]->rule | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1184 | << "' " << static_cast<uint32_t>(req.method()) << " / " | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1185 | << rules[ruleIndex]->getMethods(); | 
|  | 1186 |  | 
|  | 1187 | // any uncaught exceptions become 500s | 
|  | 1188 | try | 
|  | 1189 | { | 
| Ed Tanous | f94c4ec | 2022-01-06 12:44:41 -0800 | [diff] [blame] | 1190 | rules[ruleIndex]->handleUpgrade(req, res, | 
|  | 1191 | std::forward<Adaptor>(adaptor)); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1192 | } | 
| Patrick Williams | c596704 | 2021-10-06 12:39:54 -0500 | [diff] [blame] | 1193 | catch (const std::exception& e) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1194 | { | 
|  | 1195 | BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what(); | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 1196 | res.result(boost::beast::http::status::internal_server_error); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1197 | res.end(); | 
|  | 1198 | return; | 
|  | 1199 | } | 
|  | 1200 | catch (...) | 
|  | 1201 | { | 
|  | 1202 | BMCWEB_LOG_ERROR | 
|  | 1203 | << "An uncaught exception occurred. The type was unknown " | 
|  | 1204 | "so no information was available."; | 
| Ed Tanous | de5c9f3 | 2019-03-26 09:17:55 -0700 | [diff] [blame] | 1205 | res.result(boost::beast::http::status::internal_server_error); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1206 | res.end(); | 
|  | 1207 | return; | 
|  | 1208 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1209 | } | 
|  | 1210 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1211 | void handle(Request& req, | 
|  | 1212 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1213 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1214 | if (static_cast<size_t>(req.method()) >= perMethods.size()) | 
| Ed Tanous | 888880a | 2020-08-24 13:48:50 -0700 | [diff] [blame] | 1215 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1216 | asyncResp->res.result(boost::beast::http::status::not_found); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1217 | return; | 
| Ed Tanous | 888880a | 2020-08-24 13:48:50 -0700 | [diff] [blame] | 1218 | } | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1219 | PerMethod& perMethod = perMethods[static_cast<size_t>(req.method())]; | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1220 | Trie& trie = perMethod.trie; | 
|  | 1221 | std::vector<BaseRule*>& rules = perMethod.rules; | 
|  | 1222 |  | 
|  | 1223 | const std::pair<unsigned, RoutingParams>& found = trie.find(req.url); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1224 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1225 | unsigned ruleIndex = found.first; | 
|  | 1226 |  | 
| Ed Tanous | e662eae | 2022-01-25 10:39:19 -0800 | [diff] [blame] | 1227 | if (ruleIndex == 0U) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1228 | { | 
| Ed Tanous | 2634dcd | 2019-03-26 09:28:06 -0700 | [diff] [blame] | 1229 | // Check to see if this url exists at any verb | 
|  | 1230 | for (const PerMethod& p : perMethods) | 
|  | 1231 | { | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1232 | const std::pair<unsigned, RoutingParams>& found2 = | 
| Ed Tanous | 2634dcd | 2019-03-26 09:28:06 -0700 | [diff] [blame] | 1233 | p.trie.find(req.url); | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1234 | if (found2.first > 0) | 
| Ed Tanous | 2634dcd | 2019-03-26 09:28:06 -0700 | [diff] [blame] | 1235 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1236 | asyncResp->res.result( | 
|  | 1237 | boost::beast::http::status::method_not_allowed); | 
| Ed Tanous | 2634dcd | 2019-03-26 09:28:06 -0700 | [diff] [blame] | 1238 | return; | 
|  | 1239 | } | 
|  | 1240 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1241 | BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url; | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1242 | asyncResp->res.result(boost::beast::http::status::not_found); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1243 | return; | 
|  | 1244 | } | 
|  | 1245 |  | 
|  | 1246 | if (ruleIndex >= rules.size()) | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 1247 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1248 | throw std::runtime_error("Trie internal structure corrupted!"); | 
| Ed Tanous | 3174e4d | 2020-10-07 11:41:22 -0700 | [diff] [blame] | 1249 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1250 |  | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1251 | if ((rules[ruleIndex]->getMethods() & | 
|  | 1252 | (1U << static_cast<uint32_t>(req.method()))) == 0) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1253 | { | 
|  | 1254 | BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url | 
|  | 1255 | << " with " << req.methodString() << "(" | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1256 | << static_cast<uint32_t>(req.method()) << ") / " | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1257 | << rules[ruleIndex]->getMethods(); | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1258 | asyncResp->res.result( | 
|  | 1259 | boost::beast::http::status::method_not_allowed); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1260 | return; | 
|  | 1261 | } | 
|  | 1262 |  | 
|  | 1263 | BMCWEB_LOG_DEBUG << "Matched rule '" << rules[ruleIndex]->rule << "' " | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1264 | << static_cast<uint32_t>(req.method()) << " / " | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1265 | << rules[ruleIndex]->getMethods(); | 
|  | 1266 |  | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1267 | if (req.session == nullptr) | 
| James Feist | 7166bf0 | 2019-12-10 16:52:14 +0000 | [diff] [blame] | 1268 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1269 | rules[ruleIndex]->handle(req, asyncResp, found.second); | 
| James Feist | 7166bf0 | 2019-12-10 16:52:14 +0000 | [diff] [blame] | 1270 | return; | 
|  | 1271 | } | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1272 |  | 
|  | 1273 | crow::connections::systemBus->async_method_call( | 
| Ed Tanous | 168e20c | 2021-12-13 14:39:53 -0800 | [diff] [blame] | 1274 | [&req, asyncResp, &rules, ruleIndex, | 
|  | 1275 | found](const boost::system::error_code ec, | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1276 | const dbus::utility::DBusPropertiesMap& userInfoMap) { | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1277 | if (ec) | 
|  | 1278 | { | 
|  | 1279 | BMCWEB_LOG_ERROR << "GetUserInfo failed..."; | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1280 | asyncResp->res.result( | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1281 | boost::beast::http::status::internal_server_error); | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1282 | return; | 
|  | 1283 | } | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1284 | std::string userRole{}; | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1285 | const bool* remoteUser = nullptr; | 
|  | 1286 | std::optional<bool> passwordExpired; | 
|  | 1287 |  | 
|  | 1288 | for (const auto& userInfo : userInfoMap) | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1289 | { | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1290 | if (userInfo.first == "UserPrivilege") | 
|  | 1291 | { | 
|  | 1292 | const std::string* userRolePtr = | 
|  | 1293 | std::get_if<std::string>(&userInfo.second); | 
|  | 1294 | if (userRolePtr == nullptr) | 
|  | 1295 | { | 
|  | 1296 | continue; | 
|  | 1297 | } | 
|  | 1298 | userRole = *userRolePtr; | 
|  | 1299 | BMCWEB_LOG_DEBUG | 
|  | 1300 | << "userName = " << req.session->username | 
|  | 1301 | << " userRole = " << *userRolePtr; | 
|  | 1302 | } | 
|  | 1303 | else if (userInfo.first == "RemoteUser") | 
|  | 1304 | { | 
|  | 1305 | remoteUser = std::get_if<bool>(&userInfo.second); | 
|  | 1306 | } | 
|  | 1307 | else if (userInfo.first == "UserPasswordExpired") | 
|  | 1308 | { | 
|  | 1309 | const bool* passwordExpiredPtr = | 
|  | 1310 | std::get_if<bool>(&userInfo.second); | 
|  | 1311 | if (passwordExpiredPtr == nullptr) | 
|  | 1312 | { | 
|  | 1313 | continue; | 
|  | 1314 | } | 
|  | 1315 | passwordExpired = *passwordExpiredPtr; | 
|  | 1316 | } | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1317 | } | 
|  | 1318 |  | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1319 | if (remoteUser == nullptr) | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1320 | { | 
|  | 1321 | BMCWEB_LOG_ERROR | 
|  | 1322 | << "RemoteUser property missing or wrong type"; | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1323 | asyncResp->res.result( | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1324 | boost::beast::http::status::internal_server_error); | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1325 | return; | 
|  | 1326 | } | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1327 |  | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1328 | if (passwordExpired == std::nullopt) | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1329 | { | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1330 | if (!*remoteUser) | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1331 | { | 
|  | 1332 | BMCWEB_LOG_ERROR | 
|  | 1333 | << "UserPasswordExpired property is expected for" | 
|  | 1334 | " local user but is missing or wrong type"; | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1335 | asyncResp->res.result( | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1336 | boost::beast::http::status::internal_server_error); | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1337 | return; | 
|  | 1338 | } | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1339 | passwordExpired = false; | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1340 | } | 
|  | 1341 |  | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1342 | // Get the userprivileges from the role | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1343 | redfish::Privileges userPrivileges = | 
|  | 1344 | redfish::getUserPrivileges(userRole); | 
|  | 1345 |  | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1346 | // Set isConfigureSelfOnly based on D-Bus results.  This | 
|  | 1347 | // ignores the results from both pamAuthenticateUser and the | 
|  | 1348 | // value from any previous use of this session. | 
| Ed Tanous | b9d36b4 | 2022-02-26 21:42:46 -0800 | [diff] [blame] | 1349 | req.session->isConfigureSelfOnly = *passwordExpired; | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1350 |  | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1351 | // Modifyprivileges if isConfigureSelfOnly. | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1352 | if (req.session->isConfigureSelfOnly) | 
|  | 1353 | { | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1354 | // Remove allprivileges except ConfigureSelf | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1355 | userPrivileges = userPrivileges.intersection( | 
|  | 1356 | redfish::Privileges{"ConfigureSelf"}); | 
|  | 1357 | BMCWEB_LOG_DEBUG << "Operation limited to ConfigureSelf"; | 
|  | 1358 | } | 
|  | 1359 |  | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1360 | if (!rules[ruleIndex]->checkPrivileges(userPrivileges)) | 
|  | 1361 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1362 | asyncResp->res.result( | 
|  | 1363 | boost::beast::http::status::forbidden); | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1364 | if (req.session->isConfigureSelfOnly) | 
|  | 1365 | { | 
|  | 1366 | redfish::messages::passwordChangeRequired( | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1367 | asyncResp->res, | 
| Ed Tanous | ace85d6 | 2021-10-26 12:45:59 -0700 | [diff] [blame] | 1368 | crow::utility::urlFromPieces( | 
|  | 1369 | "redfish", "v1", "AccountService", "Accounts", | 
|  | 1370 | req.session->username)); | 
| Joseph Reynolds | 3bf4e63 | 2020-02-06 14:44:32 -0600 | [diff] [blame] | 1371 | } | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1372 | return; | 
|  | 1373 | } | 
|  | 1374 |  | 
|  | 1375 | req.userRole = userRole; | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 1376 | rules[ruleIndex]->handle(req, asyncResp, found.second); | 
| RAJESWARAN THILLAIGOVINDAN | 61dbeef | 2019-12-13 04:26:54 -0600 | [diff] [blame] | 1377 | }, | 
|  | 1378 | "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", | 
|  | 1379 | "xyz.openbmc_project.User.Manager", "GetUserInfo", | 
|  | 1380 | req.session->username); | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1381 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1382 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1383 | void debugPrint() | 
|  | 1384 | { | 
| Ed Tanous | 271584a | 2019-07-09 16:24:22 -0700 | [diff] [blame] | 1385 | for (size_t i = 0; i < perMethods.size(); i++) | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1386 | { | 
| Ed Tanous | 23a21a1 | 2020-07-25 04:45:05 +0000 | [diff] [blame] | 1387 | BMCWEB_LOG_DEBUG << boost::beast::http::to_string( | 
|  | 1388 | static_cast<boost::beast::http::verb>(i)); | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1389 | perMethods[i].trie.debugPrint(); | 
|  | 1390 | } | 
| Ed Tanous | 3dac749 | 2017-08-02 13:46:20 -0700 | [diff] [blame] | 1391 | } | 
| Ed Tanous | b4a7bfa | 2017-04-04 17:23:00 -0700 | [diff] [blame] | 1392 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1393 | std::vector<const std::string*> getRoutes(const std::string& parent) | 
|  | 1394 | { | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1395 | std::vector<const std::string*> ret; | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1396 |  | 
|  | 1397 | for (const PerMethod& pm : perMethods) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1398 | { | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1399 | std::vector<unsigned> x; | 
|  | 1400 | pm.trie.findRouteIndexes(parent, x); | 
|  | 1401 | for (unsigned index : x) | 
|  | 1402 | { | 
|  | 1403 | ret.push_back(&pm.rules[index]->rule); | 
|  | 1404 | } | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1405 | } | 
|  | 1406 | return ret; | 
|  | 1407 | } | 
|  | 1408 |  | 
|  | 1409 | private: | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1410 | struct PerMethod | 
|  | 1411 | { | 
|  | 1412 | std::vector<BaseRule*> rules; | 
|  | 1413 | Trie trie; | 
| Ed Tanous | 313a3c2 | 2022-03-14 09:27:38 -0700 | [diff] [blame] | 1414 | // rule index 0 has special meaning; preallocate it to avoid | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1415 | // duplication. | 
| Ed Tanous | 313a3c2 | 2022-03-14 09:27:38 -0700 | [diff] [blame] | 1416 | PerMethod() : rules(1) | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 1417 | {} | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1418 | }; | 
| Ed Tanous | 888880a | 2020-08-24 13:48:50 -0700 | [diff] [blame] | 1419 |  | 
|  | 1420 | const static size_t maxHttpVerbCount = | 
| Ed Tanous | cc09044 | 2020-10-07 08:20:50 -0700 | [diff] [blame] | 1421 | static_cast<size_t>(boost::beast::http::verb::unlink); | 
| Ed Tanous | 888880a | 2020-08-24 13:48:50 -0700 | [diff] [blame] | 1422 |  | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 1423 | std::array<PerMethod, maxHttpVerbCount> perMethods; | 
|  | 1424 | std::vector<std::unique_ptr<BaseRule>> allRules; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 1425 | }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 1426 | } // namespace crow |