$darkmode
registrar.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
23 #pragma once
24 
25 #include <functional>
26 #include <initializer_list>
27 #include <map>
28 #include <string>
29 #include <utility>
30 
31 #include <boost/thread/locks.hpp> // for unique_lock
32 #include <boost/thread/shared_mutex.hpp> // for shared_mutex
33 
34 #include <cloe/handler.hpp> // for Handler
35 
36 #include "oak/route_muxer.hpp" // for Muxer
37 
38 namespace oak {
39 
40 class Server;
41 
42 using Handler = cloe::Handler;
43 
44 using Response = cloe::Response;
45 
46 using Middleware = std::function<Handler(Handler)>;
47 
48 using Logger = std::function<void(const std::string&)>;
49 
57 Middleware chain_middleware(Middleware x, Middleware y);
58 
67 class Registrar {
68  public:
69  Registrar(const Registrar* r, const std::string& prefix, Middleware m);
70  virtual ~Registrar() = default;
71 
72  Registrar with(const std::string& prefix, Middleware m) const;
73  Registrar with_prefix(const std::string& prefix) const;
74  Registrar with_middleware(Middleware m) const;
75  std::string prefix() const { return prefix_; }
76  Middleware middleware() const { return middleware_; }
77  virtual void register_handler(const std::string& route, Handler h);
78 
79  protected:
80  Registrar(const std::string& prefix, Middleware m) : prefix_(prefix), middleware_(m) {}
81 
82  protected:
83  Registrar* proxy_{nullptr};
84  std::string prefix_;
85  Middleware middleware_;
86 };
87 
88 template <typename T>
90  public:
91  ProxyRegistrar(const std::map<T, Registrar*>& registrars, const std::string& prefix, Middleware m)
92  : registrars_(registrars), prefix_(prefix), middleware_(m) {}
93  explicit ProxyRegistrar(std::initializer_list<std::pair<T, Registrar*>> registrars) {
94  for (auto p : registrars) {
95  registrars_[p.first] = p.second;
96  }
97  }
98 
99  ProxyRegistrar<T> with(const std::string& prefix, Middleware m) const {
100  assert(prefix.size() == 0 || prefix[0] == '/');
101  return ProxyRegistrar<T>(registrars_, prefix_ + prefix, chain_middleware(middleware_, m));
102  }
103 
104  ProxyRegistrar<T> with_prefix(const std::string& prefix) const {
105  assert(prefix.size() > 0 && prefix[0] == '/');
106  return ProxyRegistrar<T>(registrars_, prefix_ + prefix, middleware_);
107  }
108 
109  ProxyRegistrar<T> with_middleware(Middleware m) const {
110  assert(m != nullptr);
111  return ProxyRegistrar<T>(registrars_, prefix_, chain_middleware(middleware_, m));
112  }
113 
114  std::string prefix() const { return prefix_; }
115  Middleware middleware() const { return middleware_; }
116 
117  void register_handler(const std::string& route, T select, Handler h) {
118  assert(route.size() != 0 && route[0] == '/');
119  assert(registrars_.size() != 0);
120  if (middleware_) {
121  h = middleware_(h);
122  }
123  auto endpoint = route;
124  if (prefix_.size() != 0) {
125  endpoint = prefix_ + route;
126  }
127  registrars_.at(select)->register_handler(endpoint, h);
128  }
129 
130  private:
131  std::map<T, Registrar*> registrars_;
132  std::string prefix_;
133  Middleware middleware_;
134 };
135 
143 class StaticRegistrar : public Registrar {
144  public:
145  explicit StaticRegistrar(Server* s) : Registrar("", nullptr), server_(s) {
146  assert(server_ != nullptr);
147  }
148  StaticRegistrar(Server* s, const std::string& prefix, Middleware m)
149  : Registrar(prefix, m), server_(s) {
150  assert(server_ != nullptr);
151  assert(prefix_.size() == 0 || prefix_[0] == '/');
152  }
153  virtual ~StaticRegistrar() = default;
154 
155  void register_handler(const std::string& route, Handler h) override;
156 
157  void set_prefix(const std::string& prefix) { prefix_ = prefix; }
158  void set_logger(Logger logger) { logger_ = logger; }
159 
160  const std::vector<std::string>& endpoints() const { return endpoints_; }
161 
162  protected:
163  void log(const std::string& endpoint) {
164  if (logger_) {
165  logger_(endpoint);
166  }
167  }
168 
169  protected:
170  Server* server_;
171  Logger logger_;
172  std::vector<std::string> endpoints_;
173 };
174 
187  public:
188  using StaticRegistrar::StaticRegistrar;
189 
190  void register_handler(const std::string& route, Handler h) override;
191 
197  boost::unique_lock<boost::shared_mutex> lock() {
198  return boost::unique_lock<boost::shared_mutex>(access_);
199  }
200 
201  private:
202  mutable boost::shared_mutex access_;
203 };
204 
224  public:
225  using StaticRegistrar::StaticRegistrar;
226 
230  void register_handler(const std::string& route, Handler h) override;
231 
239  void refresh_buffer();
240 
241  protected:
248  void refresh_route(const std::string& key);
249 
250  protected:
251  mutable boost::shared_mutex access_;
252  Muxer<Response> buffer_;
253  Muxer<Handler> handlers_;
254 };
255 
256 } // namespace oak
Definition: registrar.hpp:223
Definition: handler.hpp:197
Definition: registrar.hpp:89
std::function< void(const Request &, Response &)> Handler
Definition: handler.hpp:348
Definition: registrar.hpp:38
Definition: route_muxer.hpp:63
Definition: registrar.hpp:67
Definition: registrar.hpp:186
Definition: registrar.hpp:143
Definition: enum_test.cpp:29
boost::unique_lock< boost::shared_mutex > lock()
Definition: registrar.hpp:197
Middleware chain_middleware(Middleware x, Middleware y)
Definition: registrar.cpp:34
Definition: server.hpp:103