GCC Code Coverage Report


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