Line data Source code
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/beast2
8 : //
9 :
10 : #ifndef BOOST_BEAST2_SERVER_ROUTER_STATE_HPP
11 : #define BOOST_BEAST2_SERVER_ROUTER_STATE_HPP
12 :
13 : #include <boost/beast2/detail/config.hpp>
14 : #include <boost/beast2/detail/except.hpp>
15 : #include <boost/system/error_code.hpp>
16 : #include <boost/http_proto/method.hpp>
17 : #include <boost/core/detail/string_view.hpp>
18 : #include <string>
19 : #include <type_traits>
20 :
21 : namespace boost {
22 : namespace beast2 {
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 : } // beast2
102 : namespace system {
103 : template<>
104 : struct is_error_code_enum<
105 : ::boost::beast2::route>
106 : {
107 : static bool const value = true;
108 : };
109 : } // system
110 : namespace beast2 {
111 :
112 : namespace detail {
113 : struct BOOST_SYMBOL_VISIBLE route_cat_type
114 : : system::error_category
115 : {
116 : BOOST_BEAST2_DECL const char* name(
117 : ) const noexcept override;
118 : BOOST_BEAST2_DECL std::string message(
119 : int) const override;
120 : BOOST_BEAST2_DECL char const* message(
121 : int, char*, std::size_t
122 : ) const noexcept override;
123 1966 : bool failed( int ) const noexcept override
124 1966 : { return false; }
125 3 : BOOST_SYSTEM_CONSTEXPR route_cat_type()
126 3 : : error_category(0x51c90d393754ecdf )
127 : {
128 3 : }
129 : };
130 : BOOST_BEAST2_DECL extern route_cat_type route_cat;
131 : } // detail
132 :
133 : inline
134 : BOOST_SYSTEM_CONSTEXPR
135 : system::error_code
136 1966 : make_error_code(route ev) noexcept
137 : {
138 : return system::error_code{static_cast<
139 : std::underlying_type<route>::type>(ev),
140 1966 : detail::route_cat};
141 : }
142 :
143 : //------------------------------------------------
144 :
145 : class resumer;
146 :
147 : /** Function to detach a route handler from its session
148 :
149 : This holds an reference to an implementation
150 : which detaches the handler from its session.
151 : */
152 : class detacher
153 : {
154 : public:
155 : /** Base class of the implementation
156 : */
157 : struct owner
158 : {
159 : virtual resumer do_detach() = 0;
160 : virtual void do_resume(route_result const&) = 0;
161 : };
162 :
163 2 : detacher() = default;
164 : detacher(detacher const&) = default;
165 : detacher& operator=(detacher const&) = default;
166 :
167 : explicit
168 0 : detacher(
169 : owner& who) noexcept
170 0 : : p_(&who)
171 : {
172 0 : }
173 :
174 : /** Detach and invoke the given function
175 :
176 : The function will be invoked with this equivalent signature:
177 : @code
178 : void( resumer );
179 : @endcode
180 :
181 : @return A @ref route_result equal to @ref route::detach
182 : */
183 : template<class F>
184 : route_result
185 : operator()(F&& f);
186 :
187 : private:
188 : friend resumer;
189 : owner* p_ = nullptr;
190 : };
191 :
192 : //------------------------------------------------
193 :
194 : /** Function to resume a route handler's session
195 :
196 : This holds a reference to an implementation
197 : which resumes the handler's session. The resume
198 : function is returned by calling @ref detach.
199 : */
200 : class resumer
201 : {
202 : public:
203 : /** Constructor
204 :
205 : Default constructed resume functions will
206 : be empty. Invoking an empty resume function
207 : yields undefined behavior.
208 : */
209 : resumer() = default;
210 :
211 : /** Constructor
212 :
213 : Copies of resume functions behave the same
214 : as the original
215 : */
216 : resumer(resumer const&) = default;
217 :
218 : /** Assignment
219 :
220 : Copies of resume functions behave the same
221 : as the original
222 : */
223 : resumer& operator=(resumer const&) = default;
224 :
225 : /** Constructor
226 : */
227 : explicit
228 0 : resumer(
229 : detacher::owner& who) noexcept
230 0 : : p_(&who)
231 : {
232 0 : }
233 :
234 : /** Resume the session
235 :
236 : A session is resumed as if the detached
237 : handler returned the error code in `ec`.
238 :
239 : @param ec The error code to resume with.
240 : */
241 : void operator()(
242 : system::error_code const& ec = {}) const
243 : {
244 : p_->do_resume(ec);
245 : }
246 :
247 : private:
248 : detacher::owner* p_ = nullptr;
249 : };
250 :
251 : template<class F>
252 : auto
253 : detacher::
254 : operator()(F&& f) ->
255 : route_result
256 : {
257 : if(! p_)
258 : detail::throw_logic_error();
259 : std::forward<F>(f)(p_->do_detach());
260 : return route::detach;
261 : }
262 :
263 : //------------------------------------------------
264 :
265 : namespace detail {
266 : class any_router;
267 : } // detail
268 : template<class, class>
269 : class basic_router;
270 :
271 : /** Base class for request objects
272 :
273 : This is a required public base for any `Request`
274 : type used with @ref basic_router.
275 : */
276 : class basic_request
277 : {
278 : public:
279 : /** The mount path of the current router
280 :
281 : This is the portion of the request path
282 : which was matched to select the handler.
283 : The remaining portion is available in
284 : @ref path.
285 : */
286 : core::string_view base_path;
287 :
288 : /** The current pathname, relative to the base path
289 : */
290 : core::string_view path;
291 :
292 : private:
293 : friend class detail::any_router;
294 : struct match_result;
295 : http_proto::method verb_ =
296 : http_proto::method::unknown;
297 : std::string verb_str_;
298 : std::string decoded_path_;
299 : bool addedSlash_ = false;
300 : bool case_sensitive = false;
301 : bool strict = false;
302 : };
303 :
304 : //-----------------------------------------------
305 :
306 : /** Base class for response objects
307 :
308 : This is a required public base for any `Response`
309 : type used with @ref basic_router.
310 : */
311 : class basic_response
312 : {
313 : private:
314 : friend class detail::any_router;
315 : template<class, class>
316 : friend class basic_router;
317 :
318 : std::size_t pos_ = 0;
319 : std::size_t resume_ = 0;
320 : system::error_code ec_;
321 : unsigned int opt_ = 0;
322 : };
323 :
324 : } // beast2
325 : } // boost
326 :
327 : #endif
|