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