xref: /openbmc/bmcweb/http/routing/taggedrule.hpp (revision a529a6aa)
1 #pragma once
2 #include "baserule.hpp"
3 #include "dynamicrule.hpp"
4 #include "ruleparametertraits.hpp"
5 
6 #include <boost/beast/http/verb.hpp>
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 namespace crow
13 {
14 template <typename... Args>
15 class TaggedRule :
16     public BaseRule,
17     public RuleParameterTraits<TaggedRule<Args...>>
18 {
19   public:
20     using self_t = TaggedRule<Args...>;
21 
22     explicit TaggedRule(const std::string& ruleIn) : BaseRule(ruleIn) {}
23 
24     void validate() override
25     {
26         if (!handler)
27         {
28             throw std::runtime_error("no handler for url " + rule);
29         }
30     }
31 
32     template <typename Func>
33     void operator()(Func&& f)
34     {
35         static_assert(
36             std::is_invocable_v<Func, crow::Request,
37                                 std::shared_ptr<bmcweb::AsyncResp>&, Args...>,
38             "Handler type is mismatched with URL parameters");
39         static_assert(
40             std::is_same_v<
41                 void, std::invoke_result_t<Func, crow::Request,
42                                            std::shared_ptr<bmcweb::AsyncResp>&,
43                                            Args...>>,
44             "Handler function with response argument should have void return type");
45 
46         handler = std::forward<Func>(f);
47     }
48 
49     void handle(const Request& req,
50                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
51                 const std::vector<std::string>& params) override
52     {
53         if constexpr (sizeof...(Args) == 0)
54         {
55             handler(req, asyncResp);
56         }
57         else if constexpr (sizeof...(Args) == 1)
58         {
59             handler(req, asyncResp, params[0]);
60         }
61         else if constexpr (sizeof...(Args) == 2)
62         {
63             handler(req, asyncResp, params[0], params[1]);
64         }
65         else if constexpr (sizeof...(Args) == 3)
66         {
67             handler(req, asyncResp, params[0], params[1], params[2]);
68         }
69         else if constexpr (sizeof...(Args) == 4)
70         {
71             handler(req, asyncResp, params[0], params[1], params[2], params[3]);
72         }
73         else if constexpr (sizeof...(Args) == 5)
74         {
75             handler(req, asyncResp, params[0], params[1], params[2], params[3],
76                     params[4]);
77         }
78         static_assert(sizeof...(Args) <= 5, "More args than are supported");
79     }
80 
81   private:
82     std::function<void(const crow::Request&,
83                        const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>
84         handler;
85 };
86 } // namespace crow
87