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