RESTinio
Toggle main menu visibility
Loading...
Searching...
No Matches
restinio
async_chain
common.hpp
Go to the documentation of this file.
1
/*!
2
* @file
3
* @brief Common stuff for different types of async handlers chains.
4
* @since v.0.7.0
5
*/
6
7
#
pragma
once
8
9
#
include
<
restinio
/
request_handler
.
hpp
>
10
11
namespace
restinio
::
async_chain
12
{
13
14
/*!
15
* @brief Type for return value of a scheduler in a chain.
16
*
17
* A scheduler should schedule the actual processing of a request and should
18
* tell whether this scheduling was successful or not. If it was successful,
19
* schedule_result_t::ok must be returned, otherwise the
20
* schedule_result_t::failure must be returned.
21
*
22
* @since v.0.7.0
23
*/
24
enum
class
schedule_result_t
25
{
26
//! The scheduling of the actual processing was successful.
27
ok
,
28
//! The scheduling of the actual processing failed. Note, that
29
//! there is no additional information about the failure.
30
failure
31
};
32
33
/*!
34
* @brief Helper function to be used if scheduling was successful.
35
*
36
* Usage example:
37
* @code
38
* restinio::async_chain::growable_size_chain_t<>::builder_t builder;
39
* builder.add([this](auto controller) {
40
* ... // Actual scheduling.
41
* return restinio::async_chain::ok();
42
* });
43
* @endcode
44
*
45
* @since v.0.7.0
46
*/
47
[[
nodiscard
]]
48
inline
constexpr
schedule_result_t
49
ok
()
noexcept
{
return
schedule_result_t
::
ok
; }
50
51
/*!
52
* @brief Helper function to be used if scheduling failed.
53
*
54
* Usage example:
55
* @code
56
* restinio::async_chain::growable_size_chain_t<>::builder_t builder;
57
* builder.add([this](auto controller) {
58
* try {
59
* ... // Actual scheduling.
60
* return restinio::async_chain::ok(); // OK, no problems.
61
* }
62
* catch( ... ) {
63
* return restinio::async_chain::failure();
64
* }
65
* });
66
* @endcode
67
*
68
* @since v.0.7.0
69
*/
70
[[
nodiscard
]]
71
inline
constexpr
schedule_result_t
72
failure
()
noexcept
{
return
schedule_result_t
::
failure
; }
73
74
// Just a forward declaration.
75
template
<
typename
Extra_Data_Factory =
no_extra_data_factory_t
>
76
class
async_handling_controller_t
;
77
78
/*!
79
* @brief Short alias for unique_ptr to async_handling_controller.
80
*
81
* @since v.0.7.0
82
*/
83
template
<
typename
Extra_Data_Factory
=
no_extra_data_factory_t
>
84
using
unique_async_handling_controller_t
=
85
std
::
unique_ptr
<
async_handling_controller_t
<
Extra_Data_Factory
> >;
86
87
/*!
88
* @brief Short alias for a type of a scheduler to be used in async chains.
89
*
90
* @since v.0.7.0
91
*/
92
template
<
typename
Extra_Data_Factory
=
no_extra_data_factory_t
>
93
using
generic_async_request_scheduler_t
=
94
std
::
function
<
95
schedule_result_t
(
unique_async_handling_controller_t
<
Extra_Data_Factory
>)
96
>;
97
98
/*!
99
* @brief Special type to be used as an indicator that there are no more
100
* schedulers in an async chain.
101
*
102
* This type will be used in on_next_result_t variant.
103
*
104
* @since v.0.7.0
105
*/
106
struct
no_more_schedulers_t
{};
107
108
/*!
109
* @brief Special type to be used as result of async_handling_controller's
110
* on_next method.
111
*
112
* The async_handling_controller_t::on_next may return an actual scheduler to
113
* be called or (if there are no more handlers left) a special no_more_handler
114
* value. This is described by on_next_result_t variant type.
115
*
116
* @since v.0.7.0
117
*/
118
template
<
typename
Extra_Data_Factory
=
no_extra_data_factory_t
>
119
using
on_next_result_t
=
std
::
variant
<
120
generic_async_request_scheduler_t
<
Extra_Data_Factory
>,
121
no_more_schedulers_t
122
>;
123
124
// Just a forward declaration.
125
template
<
typename
Extra_Data_Factory >
126
void
127
next
( unique_async_handling_controller_t< Extra_Data_Factory > controller );
128
129
/*!
130
* @brief Interface of a controller of an async chan.
131
*
132
* All actual controllers have to implement this interface.
133
*
134
* It's assumed that implementation of that interface won't be thread
135
* safe. It means that methods like request_handle() and on_next() must
136
* not be called in parallel.
137
*
138
* @tparam Extra_Data_Factory Type of factory for creation of extra data
139
* objects for every incoming request. Should be no_extra_data_factory_t
140
* if extra data for incoming requests is not needed.
141
*
142
* @since v.0.7.0
143
*/
144
template
<
typename
Extra_Data_Factory
/*= no_extra_data_factory_t*/
>
145
class
async_handling_controller_t
146
{
147
// The next() function should call on_next() method.
148
template
<
typename
Extra_Data_Factory_For_Next >
149
friend
void
150
next
( unique_async_handling_controller_t< Extra_Data_Factory_For_Next > controller );
151
152
public
:
153
//! Short alias for request_handle type.
154
using
actual_request_handle_t
=
155
generic_request_handle_t
<
typename
Extra_Data_Factory
::
data_t
>;
156
157
//! Short alias for async_request_scheduler type.
158
using
actual_async_request_scheduler_t
=
159
generic_async_request_scheduler_t
<
typename
Extra_Data_Factory
::
data_t
>;
160
161
//! Short alias for the result type of %on_next method.
162
using
actual_on_next_result_t
=
163
on_next_result_t
<
Extra_Data_Factory
>;
164
165
virtual
~
async_handling_controller_t
() =
default
;
166
167
/*!
168
* @brief Get reference to the source request.
169
*
170
* Usage example:
171
* @code
172
* restinio::async_chain::schedule_result_t my_handler(
173
* restinio::async_chain::unique_async_handling_controller_t<> controller )
174
* {
175
* // Get access to the source request.
176
* const auto req = controller->request_handle();
177
* if( restinio::http_method_get() == req->header().method() )
178
* {
179
* ...
180
* }
181
* return restinio::async_chain::ok();
182
* }
183
* @endcode
184
*/
185
[[nodiscard]]
186
virtual
const
actual_request_handle_t
&
187
request_handle
()
const
noexcept
= 0;
188
189
private
:
190
/*!
191
* @brief Command to try find a next scheduler to be invoked.
192
*
193
* Implementation of async_handling_controller_t should switch to the
194
* next scheduler in the chain and return the scheduler to be called next.
195
* If there are no such schedulers, no_more_schedulers_t must be returned.
196
*
197
* @note
198
* This method is intended to be called by next() function.
199
*/
200
[[nodiscard]]
201
virtual
actual_on_next_result_t
202
on_next
() = 0;
203
};
204
205
namespace
impl
206
{
207
208
/*!
209
* @brief Helper to make a negative response with "Not Implemented" status.
210
*
211
* This helper will be used if there is no more schedulers to call, but
212
* the request is still not handled.
213
*
214
* @tparam Request_Handle Type of request handle that holds the source request.
215
*
216
* @since v.0.7.0
217
*/
218
template
<
typename
Request_Handle >
219
void
220
make_not_implemented_response
(
const
Request_Handle & req )
221
{
222
req->create_response(
status_not_found
(
)
).done();
223
}
224
225
/*!
226
* @brief Helper to make a negative response with "Internal Server Error" status.
227
*
228
* This helper will be used if the current scheduler returns
229
* schedule_result_t::failure.
230
*
231
* @tparam Request_Handle Type of request handle that holds the source request.
232
*
233
* @since v.0.7.0
234
*/
235
template
<
typename
Request_Handle >
236
void
237
make_internal_server_error_response
(
const
Request_Handle & req )
238
{
239
req->create_response(
status_internal_server_error
(
)
).done();
240
}
241
242
/*!
243
* @brief Helper type to be used as handler of variant values in std::visit.
244
*
245
* If there is the next async scheduler to be called it will be called.
246
* If it returns schedule_result_t::failure, then negative response will
247
* be generated and processing will be stopped.
248
*
249
* If no_more_schedulers_t is here, then negative response will be generated.
250
*
251
* @since v.0.7.0
252
*/
253
template
<
typename
Extra_Data_Factory >
254
struct
on_next_result_visitor_t
255
{
256
unique_async_handling_controller_t
<
Extra_Data_Factory
> &
m_controller
;
257
258
void
259
operator
()(
260
const
generic_async_request_scheduler_t< Extra_Data_Factory > & handler )
const
261
{
262
// We have to store request_handle before further processing because
263
// m_controller becomes empty after passing to the `handler`.
264
const
auto
req = m_controller->request_handle();
265
const
auto
schedule_result = handler( std::move(m_controller) );
266
switch
( schedule_result )
267
{
268
case
schedule_result_t
::
ok
:
269
/* nothing to do */
270
// It's assumed that handler will call next() when it'll be
271
// appropriate.
272
break
;
273
274
case
schedule_result_t
::
failure
:
275
make_internal_server_error_response( req );
276
break
;
277
}
278
}
279
280
void
281
operator
()(
282
const
no_more_schedulers_t
& )
const
283
{
284
make_not_implemented_response( m_controller->request_handle() );
285
}
286
};
287
288
}
/* namespace impl */
289
290
/*!
291
* @brief Command to try to switch to the next handler in an async chain.
292
*
293
* If an intermediate handler in an async chain doesn't complete processing
294
* of the request it should call next() function to activate the next
295
* handler in the chain.
296
*
297
* If there are no more handlers in the chain the processing of the request
298
* will be finished just inside the next() call by generating negative
299
* response.
300
*
301
* @note
302
* The handler must not call next() if it generates the response for the
303
* request:
304
* @code
305
* void actual_processor(restinio::async_chain::unique_async_handling_controller_t<> controller) {
306
* const auto req = controller->request_handle();
307
* if(request_can_be_handled(req)) {
308
* processing_of_the_request(req);
309
* req->create_response(...)
310
* ...
311
* .done(); // Request processing completed.
312
* }
313
* else {
314
* // This handler can't complete processing of the request.
315
* // Have to switch to the next handler.
316
* next(std::move(controller));
317
* }
318
*
319
* // NOTE: it's not safe to use `controller` here!
320
* }
321
* @endcode
322
*
323
* @since v.0.7.0
324
*/
325
template
<
typename
Extra_Data_Factory >
326
void
327
next
( unique_async_handling_controller_t< Extra_Data_Factory > controller )
328
{
329
std::visit(
330
impl
::
on_next_result_visitor_t
< Extra_Data_Factory >{ controller },
331
controller->on_next() );
332
}
333
334
}
/* namespace restinio::async_chain */
restinio::async_chain::async_handling_controller_t
Interface of a controller of an async chan.
Definition
common.hpp:146
restinio::async_chain::async_handling_controller_t::on_next
virtual actual_on_next_result_t on_next()=0
Command to try find a next scheduler to be invoked.
restinio::async_chain::async_handling_controller_t::~async_handling_controller_t
virtual ~async_handling_controller_t()=default
restinio::async_chain::async_handling_controller_t::request_handle
virtual const actual_request_handle_t & request_handle() const noexcept=0
Get reference to the source request.
restinio::async_chain::impl
Definition
common.hpp:206
restinio::async_chain::impl::make_internal_server_error_response
void make_internal_server_error_response(const Request_Handle &req)
Helper to make a negative response with "Internal Server Error" status.
Definition
common.hpp:237
restinio::async_chain::impl::make_not_implemented_response
void make_not_implemented_response(const Request_Handle &req)
Helper to make a negative response with "Not Implemented" status.
Definition
common.hpp:220
restinio::async_chain
Definition
common.hpp:12
restinio::async_chain::ok
constexpr schedule_result_t ok() noexcept
Helper function to be used if scheduling was successful.
Definition
common.hpp:49
restinio::async_chain::next
void next(unique_async_handling_controller_t< Extra_Data_Factory > controller)
Command to try to switch to the next handler in an async chain.
Definition
common.hpp:327
restinio::async_chain::failure
constexpr schedule_result_t failure() noexcept
Helper function to be used if scheduling failed.
Definition
common.hpp:72
restinio::async_chain::schedule_result_t
schedule_result_t
Type for return value of a scheduler in a chain.
Definition
common.hpp:25
restinio::async_chain::schedule_result_t::failure
@ failure
The scheduling of the actual processing failed. Note, that there is no additional information about t...
Definition
common.hpp:30
restinio::async_chain::schedule_result_t::ok
@ ok
The scheduling of the actual processing was successful.
Definition
common.hpp:27
restinio
Definition
sendfile_operation_default.ipp:12
restinio::status_internal_server_error
http_status_line_t status_internal_server_error()
Definition
http_headers.hpp:2286
restinio::status_not_found
http_status_line_t status_not_found()
Definition
http_headers.hpp:2244
restinio::async_chain::impl::on_next_result_visitor_t
Helper type to be used as handler of variant values in std::visit.
Definition
common.hpp:255
restinio::async_chain::impl::on_next_result_visitor_t::operator()
void operator()(const no_more_schedulers_t &) const
Definition
common.hpp:281
restinio::async_chain::impl::on_next_result_visitor_t::operator()
void operator()(const generic_async_request_scheduler_t< Extra_Data_Factory > &handler) const
Definition
common.hpp:259
restinio::async_chain::impl::on_next_result_visitor_t::m_controller
unique_async_handling_controller_t< Extra_Data_Factory > & m_controller
Definition
common.hpp:256
restinio::async_chain::no_more_schedulers_t
Special type to be used as an indicator that there are no more schedulers in an async chain.
Definition
common.hpp:106
restinio::no_extra_data_factory_t
The default extra-data-factory to be used in server's traits if a user doesn't specify own one.
Definition
request_handler.hpp:78
Generated by
1.17.0