GCC Code Coverage Report


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