GCC Code Coverage Report


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