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