xref: /openbmc/bmcweb/http/routing/dynamicrule.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #pragma once
4 #include "baserule.hpp"
5 #include "ruleparametertraits.hpp"
6 #include "websocket.hpp"
7 
8 #include <boost/beast/http/verb.hpp>
9 
10 #include <functional>
11 #include <limits>
12 #include <string>
13 #include <type_traits>
14 
15 namespace crow
16 {
17 namespace detail
18 {
19 
20 template <typename Func, typename... ArgsWrapped>
21 struct Wrapped
22 {};
23 
24 template <typename Func, typename... ArgsWrapped>
25 struct Wrapped<Func, std::tuple<ArgsWrapped...>>
26 {
27     explicit Wrapped(Func f) : handler(std::move(f)) {}
28 
29     std::function<void(ArgsWrapped...)> handler;
30 
31     void operator()(const Request& req,
32                     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
33                     const std::vector<std::string>& params)
34     {
35         if constexpr (sizeof...(ArgsWrapped) == 2)
36         {
37             handler(req, asyncResp);
38         }
39         else if constexpr (sizeof...(ArgsWrapped) == 3)
40         {
41             handler(req, asyncResp, params[0]);
42         }
43         else if constexpr (sizeof...(ArgsWrapped) == 4)
44         {
45             handler(req, asyncResp, params[0], params[1]);
46         }
47         else if constexpr (sizeof...(ArgsWrapped) == 5)
48         {
49             handler(req, asyncResp, params[0], params[1], params[2]);
50         }
51         else if constexpr (sizeof...(ArgsWrapped) == 6)
52         {
53             handler(req, asyncResp, params[0], params[1], params[2], params[3]);
54         }
55         else if constexpr (sizeof...(ArgsWrapped) == 7)
56         {
57             handler(req, asyncResp, params[0], params[1], params[2], params[3],
58                     params[4]);
59         }
60     }
61 };
62 } // namespace detail
63 
64 class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
65 {
66   public:
67     explicit DynamicRule(const std::string& ruleIn) : BaseRule(ruleIn) {}
68 
69     void validate() override
70     {
71         if (!erasedHandler)
72         {
73             throw std::runtime_error("no handler for url " + rule);
74         }
75     }
76 
77     void handle(const Request& req,
78                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
79                 const std::vector<std::string>& params) override
80     {
81         erasedHandler(req, asyncResp, params);
82     }
83 
84     template <typename Func>
85     void operator()(Func f)
86     {
87         using boost::callable_traits::args_t;
88         erasedHandler = detail::Wrapped<Func, args_t<Func>>(std::move(f));
89     }
90 
91   private:
92     std::function<void(const Request&,
93                        const std::shared_ptr<bmcweb::AsyncResp>&,
94                        const std::vector<std::string>&)>
95         erasedHandler;
96 };
97 
98 } // namespace crow
99