$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 <mutex>
29 #include <string>
30 #include <utility>
31 
32 #include <cloe/handler.hpp> // for Handler, Response
33 
34 #include "oak/route_muxer.hpp" // for Muxer
35 
36 namespace oak {
37 
38 class Server; // from oak/server.hpp
39 
40 using Middleware = std::function<cloe::Handler(cloe::Handler)>;
41 
42 using Logger = std::function<void(const std::string&)>;
43 
51 Middleware chain_middleware(Middleware x, Middleware y);
52 
61 class Registrar {
62  public:
63  Registrar(const Registrar* r, const std::string& prefix, Middleware m);
64  virtual ~Registrar() = default;
65 
66  Registrar with(const std::string& prefix, Middleware m) const;
67  Registrar with_prefix(const std::string& prefix) const;
68  Registrar with_middleware(Middleware m) const;
69  std::string prefix() const { return prefix_; }
70  Middleware middleware() const { return middleware_; }
71  virtual void register_handler(const std::string& route, cloe::Handler h);
72 
73  protected:
74  Registrar(const std::string& prefix, Middleware m) : prefix_(prefix), middleware_(m) {}
75 
76  protected:
77  Registrar* proxy_{nullptr};
78  std::string prefix_;
79  Middleware middleware_;
80 };
81 
82 template <typename T>
84  public:
85  ProxyRegistrar(const std::map<T, Registrar*>& registrars, const std::string& prefix, Middleware m)
86  : registrars_(registrars), prefix_(prefix), middleware_(m) {}
87  explicit ProxyRegistrar(std::initializer_list<std::pair<T, Registrar*>> registrars) {
88  for (auto p : registrars) {
89  registrars_[p.first] = p.second;
90  }
91  }
92 
93  ProxyRegistrar<T> with(const std::string& prefix, Middleware m) const {
94  assert(prefix.size() == 0 || prefix[0] == '/');
95  return ProxyRegistrar<T>(registrars_, prefix_ + prefix, chain_middleware(middleware_, m));
96  }
97 
98  ProxyRegistrar<T> with_prefix(const std::string& prefix) const {
99  assert(prefix.size() > 0 && prefix[0] == '/');
100  return ProxyRegistrar<T>(registrars_, prefix_ + prefix, middleware_);
101  }
102 
103  ProxyRegistrar<T> with_middleware(Middleware m) const {
104  assert(m != nullptr);
105  return ProxyRegistrar<T>(registrars_, prefix_, chain_middleware(middleware_, m));
106  }
107 
108  std::string prefix() const { return prefix_; }
109  Middleware middleware() const { return middleware_; }
110 
111  void register_handler(const std::string& route, T select, cloe::Handler h) {
112  assert(route.size() != 0 && route[0] == '/');
113  assert(registrars_.size() != 0);
114  if (middleware_) {
115  h = middleware_(h);
116  }
117  auto endpoint = route;
118  if (prefix_.size() != 0) {
119  endpoint = prefix_ + route;
120  }
121  registrars_.at(select)->register_handler(endpoint, h);
122  }
123 
124  private:
125  std::map<T, Registrar*> registrars_;
126  std::string prefix_;
127  Middleware middleware_;
128 };
129 
137 class StaticRegistrar : public Registrar {
138  public:
139  explicit StaticRegistrar(Server* s) : Registrar("", nullptr), server_(s) {
140  assert(server_ != nullptr);
141  }
142  StaticRegistrar(Server* s, const std::string& prefix, Middleware m)
143  : Registrar(prefix, m), server_(s) {
144  assert(server_ != nullptr);
145  assert(prefix_.size() == 0 || prefix_[0] == '/');
146  }
147  virtual ~StaticRegistrar() = default;
148 
149  void register_handler(const std::string& route, cloe::Handler h) override;
150 
151  void set_prefix(const std::string& prefix) { prefix_ = prefix; }
152  void set_logger(Logger logger) { logger_ = logger; }
153 
154  const std::vector<std::string>& endpoints() const { return endpoints_; }
155 
156  protected:
157  void log(const std::string& endpoint) {
158  if (logger_) {
159  logger_(endpoint);
160  }
161  }
162 
163  protected:
164  Server* server_;
165  Logger logger_;
166  std::vector<std::string> endpoints_;
167 };
168 
181  public:
182  using StaticRegistrar::StaticRegistrar;
183 
184  void register_handler(const std::string& route, cloe::Handler h) override;
185 
191  std::unique_lock<std::shared_mutex> lock() {
192  return std::unique_lock(access_);
193  }
194 
195  private:
196  mutable std::shared_mutex access_;
197 };
198 
218  public:
219  using StaticRegistrar::StaticRegistrar;
220 
224  void register_handler(const std::string& route, cloe::Handler h) override;
225 
233  void refresh_buffer();
234 
235  protected:
242  void refresh_route(const std::string& key);
243 
244  protected:
245  mutable std::shared_mutex access_;
246  Muxer<cloe::Response> buffer_;
247  Muxer<cloe::Handler> handlers_;
248 };
249 
250 } // namespace oak
Definition: registrar.hpp:217
void refresh_buffer()
Definition: registrar.cpp:129
void register_handler(const std::string &route, cloe::Handler h) override
Definition: registrar.cpp:107
void refresh_route(const std::string &key)
Definition: registrar.cpp:138
Definition: registrar.hpp:180
std::unique_lock< std::shared_mutex > lock()
Definition: registrar.hpp:191
Definition: registrar.hpp:83
Definition: registrar.hpp:61
Definition: server.hpp:44
Definition: registrar.hpp:137
std::function< void(const Request &, Response &)> Handler
Definition: cloe_fwd.hpp:65
Middleware chain_middleware(Middleware x, Middleware y)
Definition: registrar.cpp:39