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