RoutingHttpWebApp.hpp
Go to the documentation of this file.
1 // @formatter:off
2 //
3 // Balau core C++ library
4 //
5 // Copyright (C) 2017 Bora Software (contact@borasoftware.com)
6 //
7 // Licensed under the Boost Software License - Version 1.0 - August 17th, 2003.
8 // See the LICENSE file for the full license text.
9 //
10 
16 
17 #ifndef COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_SERVER_HTTP_WEB_APPS__ROUTING_HTTP_WEB_APP
18 #define COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_SERVER_HTTP_WEB_APPS__ROUTING_HTTP_WEB_APP
19 
22 
24 
64 class RoutingHttpWebApp : public HttpWebApp {
68  public: using HttpWebAppPtr = std::shared_ptr<HttpWebApp>;
69 
73  public: using Value = std::tuple<std::string, HttpWebAppPtr, HttpWebAppPtr, HttpWebAppPtr>;
74 
79 
84 
85  public: static constexpr size_t KeyIndex = 0;
86  public: static constexpr size_t GetHandlerIndex = 1;
87  public: static constexpr size_t HeadHandlerIndex = 2;
88  public: static constexpr size_t PostHandlerIndex = 3;
89 
93  public: RoutingHttpWebApp(Routing && routing_) : routing(std::move(routing_)) {}
94 
95  public: void handleGetRequest(HttpSession & session,
96  const StringRequest & request,
97  std::map<std::string, std::string> & variables) override {
98  HttpWebApp * handler = resolve(session, request);
99 
100  if (handler != nullptr) {
101  handler->handleGetRequest(session, request, variables);
102  }
103  }
104 
105  public: void handleHeadRequest(HttpSession & session,
106  const StringRequest & request,
107  std::map<std::string, std::string> & variables) override {
108  HttpWebApp * handler = resolve(session, request);
109 
110  if (handler != nullptr) {
111  handler->handleHeadRequest(session, request, variables);
112  }
113  }
114 
115  public: void handlePostRequest(HttpSession & session,
116  const StringRequest & request,
117  std::map<std::string, std::string> & variables) override {
118  HttpWebApp * handler = resolve(session, request);
119 
120  if (handler != nullptr) {
121  handler->handlePostRequest(session, request, variables);
122  }
123  }
124 
126 
127  //private: HttpWebApp * resolve(HttpSession & session, const StringRequest & request);
128  private: HttpWebApp * resolve(HttpSession & session, const StringRequest & request) {
129  const std::string_view & path = std::string_view(request.target().data(), request.target().length());
130  auto pathComponents = Util::Strings::split(path, "/");
131  std::vector<std::string_view> components;
132  components.reserve(pathComponents.size() + 1);
133  components.emplace_back("");
134  Util::Vectors::append(components, pathComponents);
135 
136  Node * node = routing.findNearest(components, [] (auto & lhs, auto & rhs) { return std::get<KeyIndex>(lhs) == rhs; }, false);
137 
138  if (node != nullptr) {
139  HttpWebApp * handler;
140 
141  switch (request.method()) {
142  case Method::get: {
143  handler = std::get<GetHandlerIndex>(node->value).get();
144  break;
145  }
146 
147  case Method::head: {
148  handler = std::get<HeadHandlerIndex>(node->value).get();
149  break;
150  }
151 
152  case Method::post: {
153  handler = std::get<PostHandlerIndex>(node->value).get();
154  break;
155  }
156 
157  default: {
158  handler = nullptr;
159  break;
160  }
161  }
162 
163  if (handler != nullptr) {
164  return handler;
165  }
166  }
167 
168  // No handler found for method.
169  sendNotFoundResponse(session, request);
170  return nullptr;
171  }
172 
173  private: void sendNotFoundResponse(HttpSession & session, const StringRequest & request);
174 
175  private: Routing routing;
176 };
177 
184 template <typename HandlerT, typename ... ParamT>
185 inline RoutingHttpWebApp::Value routingNode(const std::string & key, ParamT && ... param) {
186  auto handler = std::shared_ptr<HttpWebApp>(new HandlerT(std::move(param) ...));
187  return RoutingHttpWebApp::Value(key, handler, handler, handler);
188 }
189 
196 template <typename HandlerT>
197 inline RoutingHttpWebApp::Value routingNode(const std::string & key) {
198  auto handler = std::shared_ptr<HttpWebApp>(new HandlerT);
199  return RoutingHttpWebApp::Value(key, handler, handler, handler);
200 }
201 
205 inline RoutingHttpWebApp::Value routingNode(const std::string & key) {
206  auto handler = std::shared_ptr<HttpWebApp>(nullptr);
207  return RoutingHttpWebApp::Value(key, handler, handler, handler);
208 }
209 
210 } // namespace Balau::Network::Http::HttpWebApps
211 
212 #endif // COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_SERVER_HTTP_WEB_APPS__ROUTING_HTTP_WEB_APP
virtual void handleGetRequest(HttpSession &session, const StringRequest &request, std::map< std::string, std::string > &variables)=0
Handle a GET request.
virtual void handlePostRequest(HttpSession &session, const StringRequest &request, std::map< std::string, std::string > &variables)=0
Handle a POST request.
Manages the handling of HTTP messages and WebSocket upgrade requests in an HTTP connection.
Definition: HttpSession.hpp:46
T value
The publicly accessible data contained in the node.
Definition: ObjectTrie.hpp:98
ObjectTrieNode< T > * findNearest(const ContainerT< U, UC ... > &values, bool skipRoot=true)
Descend into the trie, locating matches of the supplied values.
Definition: ObjectTrie.hpp:2028
RoutingHttpWebApp(Routing &&routing_)
Construct a routing HTTP handler, by supplying a preformed routing trie.
Definition: RoutingHttpWebApp.hpp:93
An HTTP web application handler that routes to other handlers.
Definition: RoutingHttpWebApp.hpp:64
static std::vector< std::string_view > split(const std::string_view &input, const std::regex &delimiter, bool returnDelimiters=false, bool compress=true)
Split the input string on each of the occurrences of the specified delimiter regular expression...
Definition: Strings.hpp:1240
void handlePostRequest(HttpSession &session, const StringRequest &request, std::map< std::string, std::string > &variables) override
Handle a POST request.
Definition: RoutingHttpWebApp.hpp:115
STL namespace.
void handleGetRequest(HttpSession &session, const StringRequest &request, std::map< std::string, std::string > &variables) override
Handle a GET request.
Definition: RoutingHttpWebApp.hpp:95
void handleHeadRequest(HttpSession &session, const StringRequest &request, std::map< std::string, std::string > &variables) override
Handle a HEAD request.
Definition: RoutingHttpWebApp.hpp:105
A set of HTTP web apps provided by the Balau library.
Definition: CannedHttpWebApp.hpp:27
Abstract base class of HTTP web application handlers.
Definition: HttpWebApp.hpp:39
std::shared_ptr< HttpWebApp > HttpWebAppPtr
Shared pointer container for web app instances.
Definition: RoutingHttpWebApp.hpp:68
Abstract base class of HTTP web application handlers.
Request< StringBody > StringRequest
A request with a string body.
Definition: NetworkTypes.hpp:267
static void append(std::vector< T > &dst, const std::vector< T > &src)
Appends the source vector to the destination vector.
Definition: Vectors.hpp:105
RoutingHttpWebApp::Value routingNode(const std::string &key, ParamT &&... param)
Convenience function to make a routing node from a handler type, a string key, and the handler constr...
Definition: RoutingHttpWebApp.hpp:185
std::tuple< std::string, HttpWebAppPtr, HttpWebAppPtr, HttpWebAppPtr > Value
The type of the routing node values added to the routing trie.
Definition: RoutingHttpWebApp.hpp:73
An object based trie used for parent-child hierarchies.
virtual void handleHeadRequest(HttpSession &session, const StringRequest &request, std::map< std::string, std::string > &variables)=0
Handle a HEAD request.