GCC Code Coverage Report


Directory: ./
File: libs/http_proto/include/boost/http_proto/server/router_types.hpp
Date: 2025-12-02 19:05:14
Exec Total Coverage
Lines: 8 8 100.0%
Functions: 4 4 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/http_proto
8 //
9
10 #ifndef BOOST_HTTP_PROTO_SERVER_ROUTER_TYPES_HPP
11 #define BOOST_HTTP_PROTO_SERVER_ROUTER_TYPES_HPP
12
13 #include <boost/http_proto/detail/config.hpp>
14 #include <boost/http_proto/method.hpp>
15 #include <boost/http_proto/detail/except.hpp>
16 #include <boost/core/detail/string_view.hpp>
17 #include <boost/system/error_code.hpp>
18 #include <exception>
19 #include <string>
20 #include <type_traits>
21
22 namespace boost {
23 namespace http_proto {
24
25 /** The result type returned by a route handler.
26
27 Route handlers use this type to report errors that prevent
28 normal processing. A handler must never return a non-failing
29 (i.e. `ec.failed() == false`) value. Returning a default-constructed
30 `system::error_code` is disallowed; handlers that complete
31 successfully must instead return a valid @ref route result.
32 */
33 using route_result = system::error_code;
34
35 /** Route handler return values
36
37 These values determine how the caller proceeds after invoking
38 a route handler. Each enumerator represents a distinct control
39 action�whether the request was handled, should continue to the
40 next route, transfers ownership of the session, or signals that
41 the connection should be closed.
42 */
43 enum class route
44 {
45 /** The handler requests that the connection be closed.
46
47 No further requests will be processed. The caller should
48 close the connection once the current response, if any,
49 has been sent.
50 */
51 close = 1,
52
53 /** The handler completed the request.
54
55 The response has been fully transmitted, and no further
56 handlers or routes will be invoked. The caller should continue
57 by either reading the next request on a persistent connection
58 or closing the session if it is not keep-alive.
59 */
60 complete,
61
62 /** The handler detached from the session.
63
64 Ownership of the session or stream has been transferred to
65 the handler. The caller will not perform further I/O or manage
66 the connection after this return value.
67 */
68 detach,
69
70 /** The handler declined to process the request.
71
72 The handler chose not to generate a response. The caller
73 continues invoking the remaining handlers in the same route
74 until one returns @ref send. If none do, the caller proceeds
75 to evaluate the next matching route.
76
77 This value is returned by @ref basic_router::dispatch if no
78 handlers in any route handle the request.
79 */
80 next,
81
82 /** The handler declined the current route.
83
84 The handler wishes to skip any remaining handlers in the
85 current route and move on to the next matching route. The
86 caller stops invoking handlers in this route and resumes
87 evaluation with the next candidate route.
88 */
89 next_route,
90
91 /** The request was handled.
92
93 The route handler processed the request and prepared
94 the response serializer. The caller will send the response
95 before reading the next request or closing the connection.
96 */
97 send
98 };
99
100 //------------------------------------------------
101
102 } // http_proto
103 namespace system {
104 template<>
105 struct is_error_code_enum<
106 ::boost::http_proto::route>
107 {
108 static bool const value = true;
109 };
110 } // system
111 namespace http_proto {
112
113 namespace detail {
114 struct BOOST_SYMBOL_VISIBLE route_cat_type
115 : system::error_category
116 {
117 BOOST_HTTP_PROTO_DECL const char* name() const noexcept override;
118 BOOST_HTTP_PROTO_DECL std::string message(int) const override;
119 BOOST_HTTP_PROTO_DECL char const* message(
120 int, char*, std::size_t) const noexcept override;
121 47 BOOST_SYSTEM_CONSTEXPR route_cat_type()
122 47 : error_category(0x51c90d393754ecdf )
123 {
124 47 }
125 };
126 BOOST_HTTP_PROTO_DECL extern route_cat_type route_cat;
127 } // detail
128
129 inline
130 BOOST_SYSTEM_CONSTEXPR
131 system::error_code
132 2337 make_error_code(route ev) noexcept
133 {
134 return system::error_code{static_cast<
135 std::underlying_type<route>::type>(ev),
136 2337 detail::route_cat};
137 }
138
139 /** Return true if `rv` is a route result.
140
141 A @ref route_result can hold any error code,
142 and this function returns `true` only if `rv`
143 holds a value from the @ref route enumeration.
144 */
145 222 inline bool is_route_result(
146 route_result rv) noexcept
147 {
148 222 return &rv.category() == &detail::route_cat;
149 }
150
151 //------------------------------------------------
152
153 class resumer;
154
155 /** Function to detach a route handler from its session
156
157 This holds an reference to an implementation
158 which detaches the handler from its session.
159 */
160 class detacher
161 {
162 public:
163 /** Base class of the implementation
164 */
165 struct BOOST_SYMBOL_VISIBLE
166 owner
167 {
168 BOOST_HTTP_PROTO_DECL virtual resumer do_detach();
169 virtual void do_resume(route_result const&) = 0;
170 };
171
172 1 detacher() = default;
173 detacher(detacher const&) = default;
174 detacher& operator=(detacher const&) = default;
175
176 explicit
177 detacher(
178 owner& who) noexcept
179 : p_(&who)
180 {
181 }
182
183 /** Detach and invoke the given function
184
185 The function will be invoked with this equivalent signature:
186 @code
187 void( resumer );
188 @endcode
189
190 @return A @ref route_result equal to @ref route::detach
191 */
192 template<class F>
193 route_result
194 operator()(F&& f);
195
196 private:
197 friend resumer;
198 // Clang doesn't consider uninstantiated templates
199 // when checking for unused private fields.
200 owner* p_
201 #if defined(__clang__)
202 __attribute__((unused))
203 #endif
204 = nullptr;
205 };
206
207 //------------------------------------------------
208
209 /** Function to resume a route handler's session
210
211 This holds a reference to an implementation
212 which resumes the handler's session. The resume
213 function is returned by calling @ref detach.
214 */
215 class resumer
216 {
217 public:
218 /** Constructor
219
220 Default constructed resume functions will
221 be empty. An exception is thrown when
222 attempting to invoke an empty object.
223 */
224 resumer() = default;
225
226 /** Constructor
227
228 Copies of resume functions behave the same
229 as the original
230 */
231 resumer(resumer const&) = default;
232
233 /** Assignment
234
235 Copies of resume functions behave the same
236 as the original
237 */
238 resumer& operator=(resumer const&) = default;
239
240 /** Constructor
241 */
242 explicit
243 resumer(
244 detacher::owner& who) noexcept
245 : p_(&who)
246 {
247 }
248
249 /** Resume the session
250
251 A session is resumed as if the detached
252 handler returned the route result in @p rv.
253
254 @param ec The error code to resume with.
255
256 @throw std::invalid_argument If the object is empty.
257 */
258 void operator()(
259 route_result const& rv) const
260 {
261 if(! p_)
262 detail::throw_invalid_argument();
263 p_->do_resume(rv);
264 }
265
266 private:
267 detacher::owner* p_
268 #if defined(__clang__)
269 __attribute__((unused))
270 #endif
271 = nullptr;
272 };
273
274 template<class F>
275 auto
276 detacher::
277 operator()(F&& f) ->
278 route_result
279 {
280 if(! p_)
281 detail::throw_logic_error();
282 std::forward<F>(f)(p_->do_detach());
283 return route::detach;
284 }
285
286 //------------------------------------------------
287
288 namespace detail {
289 class any_router;
290 } // detail
291 template<class, class>
292 class basic_router;
293
294 /** Base class for request objects
295
296 This is a required public base for any `Request`
297 type used with @ref basic_router.
298 */
299 class basic_request
300 {
301 public:
302 /** The mount path of the current router
303
304 This is the portion of the request path
305 which was matched to select the handler.
306 The remaining portion is available in
307 @ref path.
308 */
309 core::string_view base_path;
310
311 /** The current pathname, relative to the base path
312 */
313 core::string_view path;
314
315 private:
316 friend class /*detail::*/any_router;
317 struct match_result;
318 http_proto::method verb_ =
319 http_proto::method::unknown;
320 std::string verb_str_;
321 std::string decoded_path_;
322 bool addedSlash_ = false;
323 bool case_sensitive = false;
324 bool strict = false;
325 };
326
327 //-----------------------------------------------
328
329 /** Base class for response objects
330
331 This is a required public base for any `Response`
332 type used with @ref basic_router.
333 */
334 class basic_response
335 {
336 private:
337 friend class /*detail::*/any_router;
338 template<class, class>
339 friend class basic_router;
340
341 std::size_t pos_ = 0;
342 std::size_t resume_ = 0;
343 system::error_code ec_;
344 std::exception_ptr ep_;
345 };
346
347 } // http_proto
348 } // boost
349
350 #endif
351