JayBeams  0.1
Another project to have fun coding.
request_dispatcher.hpp
Go to the documentation of this file.
1 #ifndef jb_ehs_request_dispatcher_hpp
2 #define jb_ehs_request_dispatcher_hpp
3 
4 #include <jb/ehs/base_types.hpp>
5 
6 #include <atomic>
7 #include <functional>
8 #include <map>
9 #include <mutex>
10 
11 namespace jb {
12 namespace ehs {
13 
14 /**
15  * Define the interface for request handlers.
16  *
17  * An Embedded HTTP Server receives HTTP requests, locates the correct
18  * handler for it based on the path component of the URL, and then
19  * passes on the request to the handler, which must implement the
20  * Callable interface defined by this type.
21  */
22 using request_handler =
23  std::function<void(request_type const&, response_type&)>;
24 
25 /**
26  * Holds a collection of HTTP request handlers and forwards requests.
27  */
29 public:
30  /**
31  * Create a new empty dispatcher.
32  *
33  * @param server_name the content of the 'server' HTTP response header.
34  */
35  explicit request_dispatcher(std::string const& server_name);
36 
37  /**
38  * Add a new handler.
39  *
40  * @param path the path that this handler is responsible for.
41  * @param handler the handler called when a request hits a path.
42  *
43  * @throw std::runtime_error if the path already exists
44  */
45  void add_handler(std::string const& path, request_handler&& handler);
46 
47  /**
48  * Process a new request using the right handler.
49  *
50  * Returns the response to send back to the client. The handler
51  * typically creates a normal 200 response, but other responses can
52  * be created by the client. The dispatcher automatically creates
53  * 404 responses if the request path does not have a handler
54  * registered, and 500 responses if there is an exception handling
55  * the request.
56  *
57  * @param request the HTTP request to process
58  * @returns a HTTP response to send back to the client.
59  */
60  response_type process(request_type const& request);
61 
62  //@{
63  /**
64  * Event counters.
65  *
66  * A series of functions to count interesting events.
67  * TODO(coryan) this should really be a separate class that can
68  * count any number of metrics, including maps, histograms, rates,
69  * etc. Look at prometheus.io for inspiration.
70  */
71  /// Count a new connection opened
74  }
75  /// Returns the count of open connections
76  long get_open_connection() const {
77  return open_connection_;
78  }
79  /// Count a new connection closed
82  }
83  /// Get the count of close connections
84  long get_close_connection() const {
85  return close_connection_;
86  }
87 
88  /// Count a successful read
89  void count_read_ok() {
90  ++read_ok_;
91  }
92  /// Get the count of successful reads
93  long get_read_ok() const {
94  return read_ok_;
95  }
96  /// Count a write errors
98  ++read_error_;
99  }
100  /// Get the count write errors
101  long get_read_error() const {
102  return read_error_;
103  }
104 
105  /// Get count of responses with invalid codes (outside the [100,600) range).
106  long get_write_invalid() const {
107  return write_invalid_;
108  }
109 
110  /// Get the count write in the 100 range
111  long get_write_100() const {
112  return write_100_;
113  }
114  /// Get the count write in the 200 range
115  long get_write_200() const {
116  return write_200_;
117  }
118  /// Get the count write in the 300 range
119  long get_write_300() const {
120  return write_300_;
121  }
122  /// Get the count write in the 400 range
123  long get_write_400() const {
124  return write_400_;
125  }
126  /// Get the count write in the 500 range
127  long get_write_500() const {
128  return write_500_;
129  }
130  /// Count a write successes
131  void count_write_ok() {
132  ++write_ok_;
133  }
134  /// Get the count write successes
135  long get_write_ok() const {
136  return write_ok_;
137  }
138  /// Count a write errors
140  ++write_error_;
141  }
142  /// Get the count write errors
143  long get_write_error() const {
144  return write_error_;
145  }
146 
147  /// Count accept successes
149  ++accept_ok_;
150  }
151  long get_accept_ok() const {
152  return accept_ok_;
153  }
154  /// Count accept errors
156  ++accept_error_;
157  }
158  long get_accept_error() const {
159  return accept_error_;
160  }
161 
162  /// Count accept requests on closed acceptors (rare)
164  ++accept_closed_;
165  }
166  long get_accept_closed() const {
167  return accept_closed_;
168  }
169  //@}
170 
171  /**
172  * Append the internal metrics to the body of @a res.
173  *
174  * @param res a http response where we will append the metrics.
175  */
176  void append_metrics(response_type& res) const;
177 
178 private:
179  /**
180  * Create a 500 response.
181  *
182  * @param request the request that triggered this response
183  * @returns a 500 HTTP response formatted to match the version of
184  * the @a request.
185  */
186  response_type internal_error(request_type const& request);
187 
188  /**
189  * Create a 404 response.
190  *
191  * @param request the request that triggered this response
192  * @returns a 404 HTTP response formatted to match the version of
193  * the @a request.
194  */
195  response_type not_found(request_type const& request);
196 
197  /**
198  * Find the request handler for the given path.
199  *
200  * @param path the request path
201  * @returns a pair with the request handler (if any) and a boolean.
202  * The boolean is set to false if the path was not found.
203  */
204  std::pair<request_handler, bool> find_handler(beast::string_view path) const;
205 
206  /**
207  * Update the response code counters based on @a res.
208  */
209  void update_response_counter(response_type const& res);
210 
211  //@{
212  /**
213  * Internally updated event counters.
214  *
215  * These event counters are only updated internally, the clients of
216  * the class can query the counters, but not update them.
217  */
218  /// Count responses with invalid codes (outside the [100,600) range).
220  ++write_invalid_;
221  }
222  /// Count a write in the 100 range
224  ++write_100_;
225  }
226  /// Count a write in the 200 range
228  ++write_200_;
229  }
230  /// Count a write in the 300 range
232  ++write_300_;
233  }
234  /// Count a write in the 400 range
236  ++write_400_;
237  }
238  /// Count a write in the 500 range
240  ++write_500_;
241  }
242  //@}
243 
244 private:
245  /// Protect the critical sections
246  mutable std::mutex mu_;
247 
248  /// The collection of handlers
249  std::map<std::string, request_handler> handlers_;
250 
251  /// The name of the server returned in all HTTP responses.
252  std::string server_name_;
253 
254  /// Multiple counters
255  std::atomic<long> open_connection_;
256  std::atomic<long> close_connection_;
257  std::atomic<long> read_ok_;
258  std::atomic<long> read_error_;
259  std::atomic<long> write_invalid_;
260  std::atomic<long> write_100_;
261  std::atomic<long> write_200_;
262  std::atomic<long> write_300_;
263  std::atomic<long> write_400_;
264  std::atomic<long> write_500_;
265  std::atomic<long> write_ok_;
266  std::atomic<long> write_error_;
267  std::atomic<long> accept_ok_;
268  std::atomic<long> accept_error_;
269  std::atomic<long> accept_closed_;
270 };
271 
272 } // namespace ehs
273 } // namespace jb
274 
275 #endif // jb_ehs_request_dispatcher_hpp
long get_open_connection() const
Returns the count of open connections.
std::atomic< long > close_connection_
response_type not_found(request_type const &request)
Create a 404 response.
std::map< std::string, request_handler > handlers_
The collection of handlers.
beast::http::request< beast::http::string_body > request_type
The request type used for JayBeams Embedded HTTP Servers.
Definition: base_types.hpp:17
std::atomic< long > open_connection_
Multiple counters.
void count_write_error()
Count a write errors.
void count_accept_ok()
Count accept successes.
void count_open_connection()
Event counters.
long get_read_ok() const
Get the count of successful reads.
void count_write_100()
Count a write in the 100 range.
long get_close_connection() const
Get the count of close connections.
void append_metrics(response_type &res) const
Append the internal metrics to the body of res.
void count_write_invalid()
Internally updated event counters.
void count_write_ok()
Count a write successes.
void count_accept_closed()
Count accept requests on closed acceptors (rare)
Holds a collection of HTTP request handlers and forwards requests.
std::atomic< long > write_invalid_
long get_write_400() const
Get the count write in the 400 range.
beast::http::response< beast::http::string_body > response_type
The response type used for JayBeams Embedded HTTP Servers.
Definition: base_types.hpp:20
request_dispatcher(std::string const &server_name)
Create a new empty dispatcher.
void count_write_500()
Count a write in the 500 range.
response_type internal_error(request_type const &request)
Create a 500 response.
void count_close_connection()
Count a new connection closed.
std::mutex mu_
Protect the critical sections.
void count_read_error()
Count a write errors.
long get_write_invalid() const
Get count of responses with invalid codes (outside the [100,600) range).
std::function< void(request_type const &, response_type &)> request_handler
Define the interface for request handlers.
void count_read_ok()
Count a successful read.
long get_write_100() const
Get the count write in the 100 range.
std::string server_name_
The name of the server returned in all HTTP responses.
void count_write_200()
Count a write in the 200 range.
long get_write_300() const
Get the count write in the 300 range.
long get_write_500() const
Get the count write in the 500 range.
std::atomic< long > accept_closed_
long get_read_error() const
Get the count write errors.
void count_write_400()
Count a write in the 400 range.
long get_write_200() const
Get the count write in the 200 range.
void update_response_counter(response_type const &res)
Update the response code counters based on res.
long get_write_error() const
Get the count write errors.
void count_accept_error()
Count accept errors.
response_type process(request_type const &request)
Process a new request using the right handler.
std::pair< request_handler, bool > find_handler(beast::string_view path) const
Find the request handler for the given path.
long get_write_ok() const
Get the count write successes.
void count_write_300()
Count a write in the 300 range.
The top-level namespace for the JayBeams library.
Definition: as_hhmmss.hpp:7
void add_handler(std::string const &path, request_handler &&handler)
Add a new handler.